Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

用 Python 中的 web3.py 库开发 Dapp

常德小学生
3564 1 0
什么是 DApp
. G- |$ _$ v; x2 T" X. f/ m) P5 f' r8 v
“DApp”代表去中心化应用程序。与传统应用程序一样,去中心化应用程序也有前端(客户端)和后端(服务器端)。DApp 的用户界面可以用任何语言编写(就像传统应用程序一样),并且可以调用其后端。那么,Dapps 与传统应用程序有何不同?DApp 的后端代码运行在分散的对等网络(即区块链)上。您可能听说过 BitTorrent、Tor、Popcorn Time——它们是在点对点网络上运行但不在区块链上运行的 DApp。区块链 DApp 有自己的后端代码,称为智能合约,可以部署到区块链(最常见的是以太坊)。智能合约定义了整个 DApp 的逻辑。它是使用区块链作为后端的命脉。那么Python 开发人员可以在哪里利用它?重点来了——web3。Web3 是一组库,允许您与本地或远程以太坊区块链进行交互。简单地说,web3 是与您的后端(区块链)通信的桥梁。幸运的是,以太坊开发人员已经制作了一个 python 库 web3.py 用于与以太坊进行交互。它的 API 源自 web3 的 JavaScript 版本。因此,除了 web3.js,我们也可以通过 web3.py 库与区块链进行交互。
6 o8 M1 u+ o! V- q) i& I8 A( `, W' A% c# x, Z
Dapps 开发包括三个简单的步骤:7 V. @( w0 F2 q+ m( T$ h
  • 在区块链网络上部署智能合约
  • 从部署的智能合约中读取数据
  • 将交易发送到部署的智能合约
    5 w& s9 p$ V% Y
我们将在带有 web3.py 库的 python 环境中一步一步地进行这三个操作要与区块链交互,我们必须连接到任何完全同步的节点。在本教程中,我们指向一个 Infura 节点。确保你有一个以太坊钱包(使用 Metamask chrome 扩展或 myetherwallet 创建以太坊钱包并安全地存储你的私钥)并在其中添加一些测试 Ether 以进行操作。2 G" x9 J3 `5 j6 }9 L: z0 O4 k( K  z: ~
* s; f; h0 i" f
安装
7 J3 R) G8 U7 K4 c5 N% m
  _2 B, J/ |: T, s/ D+ SPython 2.7 +
, Z: `. A" f, @1 d' W7 iNode.js0 J; x" r+ Q& s$ ^' K
Truffle
. C0 `5 B3 L% M" Z( z- F
; `, y8 {+ P5 s/ ^9 ~2 E/ l8 E2 ?
1 b1 b, Z  a# Nnpm install -g truffle0 O# J( J0 x5 q' |
Pip
4 e3 l% K1 Z' Enpm i pip9 V: P" L- s1 A- @- t. ], v9 J
web3.py3 X' q* v5 B6 I$ h8 G
pip install web3" M, h; [* W4 S' s7 t/ m5 a0 d
1 J$ B  H3 H4 i3 E* |
- ?* r4 c9 D% i" n" ^) m
Infura 项目 API
9 o+ v1 o/ ^. I9 D2 c- o7 ?9 ^前往 Infura 网站并注册。创建一个新项目并复制 Ropsten Infura RPC URL。我们将把我们的智能合约部署到 Ropsten 测试网络。/ J/ y, [; w9 V

# \" N5 J4 R7 ]' @智能合约
2 V$ X+ y3 `+ `  y
7 P3 I8 a0 i0 I  Y每个程序员都用他们最喜欢的编程语言执行了一个“hello world”程序,以了解运行该语言的基础知识。这是我们使用 Solidity 语言编写的简单的“hello world”版本的智能合约,我们可以在区块链上添加问候语并检索它。Solidity 是编写智能合约最常用的语言,它编译为可以在节点上运行的以太坊虚拟机上执行的字节码。
1 @% t2 a, a; M" ^1 `/ O) E% F# E0 R1 x& m
  1. pragma solidity ^0.5.7;
    1 C0 h* l$ `- p& C- q3 X" s' t
  2. contract greeter{
    / T, m  o2 e3 }7 d
  3.     string greeting;
    + R% \, |% k9 B. b1 R; p
  4.     function greet(string memory _greeting)public{
    ( y, r2 K3 r& I2 }7 v8 ?) R
  5.         greeting=_greeting;
    / Q& @) a3 q' ]. b8 P) T: e$ s0 v
  6.     }
    3 I& L2 p% g# \; d/ `
  7.     function getGreeting() public view returns(string memory) {
      D  U9 [. ?1 j0 m: X' N
  8.         return greeting;
    4 I0 }4 A4 A9 P* R1 P6 j2 K
  9.     }
    4 h- \2 l6 ]0 ?* c) K$ m
  10. }7 Q; F9 G, X+ `  l( E. c
复制代码

3 ^$ X) g: q$ a3 k$ d1 m- q6 g) I- ~3 N- K- _& ^7 }
您可以通过传递字符串值使用 greet() 方法添加问候语,并使用 getGreting() 方法检索问候语。
9 z7 ]9 p- j  k# u0 y$ J( Y. x6 o" W% @
1. 在区块链网络上部署智能合约8 G* m! q" L5 x) Z3 I& G4 K
, S% q" N. B3 H" I0 V7 \$ w
a) 创建项目:
" R0 L9 W4 g) D2 X( S. _! r( U; H; I+ h! I, j: O
mkdir pythonDapp& f4 o) R- I- I
cd pythonDapp
0 y4 C4 p0 R7 R% U% ~2 Ztruffle init
* L! X. v6 m1 x! s* m8 V1 ?
) Y! D5 S# W/ e+ \1 v+ {
9 r2 Q' Q8 {- C8 g' i成功初始化项目后,转到您的文件夹并在 /contracts目录中创建 greeter.sol 文件。在网络上部署合约之前,我们必须编译它并构建工件。
$ }7 U  z  R$ R/ d: n; B: |: m  p/ c& T/ {0 H0 w3 |9 b- W& r
b) 智能合约的编译:因此,对于编译,我们将使用 Truffle solc 编译器。在您的主目录中,运行以下命令:! k9 m" q% a& S$ [; D( @; ?

. `1 o) Q; Z9 e4 C
7 ]2 U" W; c6 [# l+ T6 {
/ N  @7 R) S6 D7 gtruffle compile
3 S1 f7 X* a. i; w- P! p(or)
1 `2 ~8 k  a* C( D0 m4 ytruffle.cmd compile #(for windows only)1 L- C; R- E$ n  x- I9 S! P- Z

. C. \# \# O0 U8 S. o2 [. ^' Q4 i" x6 ~
上面的命令将在 /contracts 目录中编译你的合约,并在 /build 目录中创建二进制工件文件 greeter.json。
! j+ w: p/ X5 G; B( A" E  T& N3 U# T6 s! [; ?
c) 部署合约:打开您的 Python IDLE 编辑器,并在主目录 deploy.py 中使用以下代码创建一个新文件,然后在您的目录中运行 py deploy.py。
1 F# _, T7 u( R1 k5 B# j# h# e2 z' N0 K' H
  1. import json
    # P$ s0 c% Z5 C. w& m. R* A; Y9 C
  2. from web3 importWeb3, HTTPProvider9 y) d' u; j$ J
  3. from web3.contract importConciseContract/ R3 p$ A9 S0 }* W1 m  {6 M  ?/ t
  4. # web3.py instance
    ' O2 Z8 F7 d% N% L
  5. w3 = Web3(HTTPProvider("https://ropsten.infura.io/v3/<API key>"))0 Y* r8 F0 j% Y' g9 v# q) W2 g
  6. print(w3.isConnected())
    3 }9 j5 K2 N; e# o" N* f2 B5 g
  7. key="<Private Key here with 0x prefix>"
    & i( p7 F9 L- k1 D. C
  8. acct = w3.eth.account.privateKeyToAccount(key)9 r2 j& y( d2 I; b
  9. # compile your smart contract with truffle first! ~3 ]' d( q! J# y6 _! @
  10. truffleFile = json.load(open('./build/contracts/greeter.json')), m) c7 |: k( y, v  q& b( `- @* d
  11. abi = truffleFile['abi']2 V8 `4 \' t6 A
  12. bytecode = truffleFile['bytecode']
    $ F/ d0 S0 Z4 P2 L$ Z
  13. contract= w3.eth.contract(bytecode=bytecode, abi=abi)' n) b  d. H* ]) m& @
  14. #building transaction9 j. \4 M2 h* e/ k7 Z
  15. construct_txn = contract.constructor().buildTransaction({
    3 W1 h8 _( B% p8 C
  16. 'from': acct.address,
    ' L+ ]  @3 i# e- T2 r& O: o% z9 b
  17. 'nonce': w3.eth.getTransactionCount(acct.address),, O1 ^5 e! t6 E  w% ^
  18. 'gas': 1728712,
    * `( N4 L, s: z) h3 N
  19. 'gasPrice': w3.toWei('21', 'gwei')})- Q% g, @, N& z  b
  20. signed = acct.signTransaction(construct_txn)& F4 |) _% T5 K  E# }+ c' L& \. J
  21. tx_hash=w3.eth.sendRawTransaction(signed.rawTransaction)3 _* \" b0 G% g2 u4 W7 @5 n
  22. print(tx_hash.hex())
    * Z- G4 d7 J5 Q; [/ F" s# U4 ]$ r
  23. tx_receipt = w3.eth.waitForTransactionReceipt(tx_hash)
    6 K" r+ N, c7 z: y! U1 H. ]
  24. print("Contract Deployed At:", tx_receipt['contractAddress'])
复制代码
/ l% ?8 h9 R  X1 N. p
1 B9 G: q- n. ]; ?& q

6 k( c6 h3 G( I3 w# o& d: D- ?这是我所做的:: @" G6 S7 p: p# k: G$ \% A3 K7 K
& V  p: R+ D7 I0 R# g
导入的 web3 库和所有其他必需的模块
* r' p# w; o5 d0 X$ G通过指向 Ropsten Infura 节点启动 web3 提供程序
2 J$ S+ T2 m0 T  l* |- o% V添加了用于签署交易的帐户地址和私钥。不要忘记在代码中添加您的凭据。
2 |5 \5 S" d" {( q( s, F9 M/ o通过指向 Truffle 编译的工件文件greeter.json的abi和字节码启动合约实例
2 w4 B( ~4 B. N1 t添加了带有随机数、gas、gasPrice 等参数的construct_txn。此处,gas 是指交易应在以太坊中使用和支付的最大计算资源量。gasPrice 是指在交易中使用该数量的 gas 时的最小 Ether 数量。to 指的是您发送交易的地址。仅当您将 Ether 发送到帐户或智能合约时才需要 to 参数。; d" `) S* N1 X
使用我们的私钥签署交易并在网络上广播。
! o% u; S7 S' p! D7 ?8 z  q在控制台中记录交易哈希和部署的合约地址。根据以太坊的说法,事务处理时间 <20 秒。所以你必须等待 20 秒才能获得部署的合约地址。您的后端现在已成功部署在以太坊区块链上。现在您可以使用此地址与您的智能合约进行交互。复制此合约地址。: l/ Y. T0 \9 a$ x! i; o* f; b( X' _
2. 向部署的合约发送交易
2 i( }+ T! P* z# A
4 C9 @  d* ~; o在我们的合约中,有一个方法greet()。我们可以单独使用这种方法在我们的合同中添加问候语。让我们看看我们如何使用 web3.py 来做到这一点。打开您的 Python IDLE 编辑器并使用以下代码创建一个新文件 sign.py。然后在您的目录中运行 py sign.py。0 P% M, D/ y# p/ g
  1. import json3 [" Y. D3 r& b/ {. b
  2. from web3 importWeb3, HTTPProvider
    ' n( Q% U7 x, C! y* |, A
  3. from web3.contract importConciseContract
    7 Y/ O# z$ s; C$ n* N) ?' A/ [
  4. # compile your smart contract with truffle first' t  v) `" Y, H- P- A. F
  5. truffleFile = json.load(open('./build/contracts/greeter.json'))+ _  c3 f5 f; M2 ]" v. g0 R
  6. abi = truffleFile['abi']
    5 K: [8 Y1 e8 m3 L
  7. bytecode = truffleFile['bytecode']3 q9 F4 R+ S6 v4 z' U5 K
  8. # web3.py instance
    6 H8 ~* v  f% h( d1 P$ \: u# w
  9. w3 = Web3(HTTPProvider("https://ropsten.infura.io/v3/<API key>")) #modify+ \! |7 c& y, J9 f' X/ b
  10. print(w3.isConnected())
    1 _% C- A' d' s: i- I
  11. contract_address = Web3.toChecksumAddress("<Deployed Contract Address here>") #modify  E3 D5 [! j( b+ x1 L9 j6 b
  12. key="<Private key with 0x prefix here>"#modify1 J7 D8 l, f# m7 w5 [
  13. acct = w3.eth.account.privateKeyToAccount(key); R2 J( {9 i/ L  J
  14. account_address= acct.address' h+ v$ o7 n# m. y; A& f' Z
  15. # Instantiate and deploy contract
    ! ^/ P$ B! x2 g8 a6 Q
  16. contract = w3.eth.contract(abi=abi, bytecode=bytecode)
    / Y% R1 d1 W: X7 n; u8 @+ {- L
  17. # Contract instance
    9 C! `$ n7 {" M3 M/ A
  18. contract_instance = w3.eth.contract(abi=abi, address=contract_address)
    ; u: [8 p3 {* ]: c+ F) {( d3 M+ H* F
  19. # Contract instance in concise mode
    . u; A  D8 a+ t0 m9 t+ u9 l# B
  20. #contract_instance = w3.eth.contract(abi=abi, address=contract_address, ContractFactoryClass=ConciseContract)# E- v4 J8 z1 @" [. W- s. q
  21. tx = contract_instance.functions.greet("Hello all my goody people").buildTransaction({'nonce': w3.eth.getTransactionCount(account_address)})
    : o/ v  c( O& Y9 ~: H% p
  22. #Get tx receipt to get contract address
    * U7 ?9 a0 H( ]/ I8 `7 X, q
  23. signed_tx = w3.eth.account.signTransaction(tx, key)- F& v9 n0 H/ o1 }
  24. #tx_receipt = w3.eth.getTransactionReceipt(tx_hash)& A9 Z' h9 v/ Z6 n! e9 b. V/ Z
  25. hash= w3.eth.sendRawTransaction(signed_tx.rawTransaction)
    8 D% i$ r  ?7 q- t, T6 _
  26. print(hash.hex())
复制代码
7 ?; Q* D$ P- @

8 H: Q3 v; y- v) e& ^( n! M  W" n, D" B! U9 I+ E& C! v
这是我所做的:6 w5 Q% V) q9 Q/ f7 }2 T
( P. D" T) y) c
导入的 web3 库和所有其他必需的模块
9 h9 Q7 E, \* ~% L: B通过指向 Ropsten Infura 节点启动 web3 提供程序
# h6 U# n/ y. _; \/ m添加了用于签署交易的帐户地址和私钥+ u9 ?: ~$ `1 x; N2 u2 _
通过指向 Truffle 编译的工件文件greeter.json的abi和字节码启动合约实例
6 W7 b5 y1 @8 d+ D" {3 V创建 tx 对象以添加问候语“hello all my goody people”并建立交易8 |2 P) Y8 h1 j
使用我们的私钥签署交易并在网络上广播。
! `3 H/ I" _5 m  R  T- X5 O在控制台中记录交易哈希。您可以使用您的交易哈希在 etherscan 上检查交易状态。一旦交易被矿工验证,我们的问候语将被添加到区块链上。您可以使用 getGreeting() 函数检索问候语,如下所述。
) g: I; T( Y: p# `$ T2 N4 [3. 从部署的智能合约中读取数据
2 r3 @; G* V- b; @9 A# ~5 \+ b: u" N$ r6 g; |/ U
在我们的合约中,有一个方法 getGreeting() 可以检索我们在区块链中添加的问候语。我们将使用 web3.py 调用此方法 打开您的 Python IDLE 编辑器并使用以下代码创建一个新文件 read.py。运行 py read.py 读取问候语。& Z0 S. c7 H# |8 v; n; G
  1. - u/ K1 _! q( `0 {' W- i5 \
  2. import json
    $ v$ A. h" ]6 ?; w/ {8 ]
  3. from web3 importWeb3, HTTPProvider
    5 b  E) @  Y( v( Y% l( V
  4. from web3.contract importConciseContract
    . i2 t- H7 Y1 B
  5. # compile your smart contract with truffle first
    ! p9 C5 ?9 a% M3 h6 p+ {) p# E
  6. truffleFile = json.load(open('./build/contracts/greeter.json')); {0 L( E4 V- i# q
  7. abi = truffleFile['abi']2 [+ Y: E4 H* U% P* y9 C) B. x  h
  8. bytecode = truffleFile['bytecode']
    " z) i+ \% @. B
  9. # web3.py instance
    3 c7 L3 c" S. ^
  10. w3 = Web3(HTTPProvider("https://ropsten.infura.io/<ApI Key here>"))
    % u0 u5 V& v4 o# ?8 S' c5 }2 b5 l8 l
  11. print(w3.isConnected())3 g  }. c: J: w! N& m! {1 P
  12. contract_address = Web3.toChecksumAddress("<Deployed Contract Address here>")
    . P7 F: n) F1 B$ E  z
  13. # Instantiate and deploy contract
    3 q4 N$ T7 p" |8 a
  14. contract = w3.eth.contract(abi=abi, bytecode=bytecode)
    + x' ]& o& H" l' S; |; c
  15. # Contract instance1 V+ h( M; P& r# \% H
  16. contract_instance = w3.eth.contract(abi=abi, address=contract_address)% A8 w9 P; u8 l# d" c+ j
  17. # Contract instance in concise mode
    + B& o" Y# _1 U  V& _9 D
  18. #contract_instance = w3.eth.contract(abi=abi, address=contract_address, ContractFactoryClass=ConciseContract)
      K: O% v6 I, j% v( i
  19. # Getters + Setters for web3.eth.contract object ConciseContract* u( R8 C7 f5 F; _2 `; U
  20. #print(format(contract_instance.getGreeting()))
    ' O, e# Z6 D, G7 ~+ M: S5 y
  21. print('Contract value: {}'.format(contract_instance.functions.getGreeting().call()))
复制代码

  u- W9 g! M) w; Y* ?% L  n" B  q6 q
# H6 p+ `, Z' o+ [' V% N- C( R$ M; X. E$ |, D! W$ {$ @) e4 D
这是我所做的:: w# B. c9 F! J
* D! `2 p3 u% r* ?, b( [
导入的 web3 库和所有其他必需的模块
6 K: ?8 t4 O) d% Z+ N% z1 V: v通过指向 Ropsten Infura 节点启动 web3 提供程序% O$ k! @! P' ~6 G' }' f, N1 m
通过指向 abi 和 contract_Address 创建合约实例(来自上一步)
( b% j' J: Q8 e4 G: t; {$ J调用 getGreeting() 方法并在控制台打印结果
$ w( C% `& L9 u4 {$ V4 |结论3 N6 n8 c1 U! q" Z6 t: y
5 {9 ^, F$ Y/ }/ p
您现在应该了解如何使用 web3.py 部署、交互和签署交易。让我们通过查看我使用 web3.py 创建的实时 DApp 并在此处使用 Flask 作为前端服务器来将所有部分组合在一起。它将帮助您更深入地了解使用 Python 进行 DApp 开发。
1 f; x+ `) k) M& g" B6 s) L, G$ m2 D8 V" t
  h) n8 j: O- m1 N$ }
参考 @温室小书生室dpython利用web3.py开发以太坊应用dapp的实战教程; Z5 _' T+ ^  y5 v9 X
标签: Python Python Python
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

常德小学生 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    13