Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

用 Python 中的 web3.py 库开发 Dapp

常德小学生
2729 1 0
什么是 DApp) j9 h) i6 D  H! k
# f5 U7 t! ~2 c% _
“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 库与区块链进行交互。
: H' l4 J; b' J0 s7 \. S
! u/ B0 c, L+ }9 I4 p9 z7 PDapps 开发包括三个简单的步骤:1 F" u7 d2 }1 Z- F6 _# \3 e& J" P; {
  • 在区块链网络上部署智能合约
  • 从部署的智能合约中读取数据
  • 将交易发送到部署的智能合约6 }( h3 N( h6 n: J1 ^( U
我们将在带有 web3.py 库的 python 环境中一步一步地进行这三个操作要与区块链交互,我们必须连接到任何完全同步的节点。在本教程中,我们指向一个 Infura 节点。确保你有一个以太坊钱包(使用 Metamask chrome 扩展或 myetherwallet 创建以太坊钱包并安全地存储你的私钥)并在其中添加一些测试 Ether 以进行操作。
8 X; t% `3 g! J2 O! x8 K+ p! i
9 O& d4 Z3 G! C# [) x. Y安装6 `" `- S8 Y( `2 w9 i8 n* n, I

8 b) ~* R4 r7 f" WPython 2.7 +
/ i' [& B$ r2 h2 H0 z+ ^' H" _Node.js
: k) r+ p/ g' d4 m1 ?Truffle+ v% ~0 [1 l- A% x* a3 k

9 |; n9 B1 `+ i! r2 o" @* ]8 o. U3 e' Z
npm install -g truffle
% v* j; X6 H. {3 X# g# z) Y! PPip
% \" ]) r7 A& t2 a, n* knpm i pip; J* ^8 w+ ~# D9 E% b9 d
web3.py: Y3 j+ z  d5 p) n- n1 G% z. H
pip install web3
5 n6 K6 J, g0 X) t1 m2 k
/ w' p. ^& _- N+ s" x& K( M3 i  C* A! Y- F
Infura 项目 API
6 E3 a9 W& z: x* d! c前往 Infura 网站并注册。创建一个新项目并复制 Ropsten Infura RPC URL。我们将把我们的智能合约部署到 Ropsten 测试网络。
: x8 e3 e5 ~& Y0 I4 Q6 |+ z* @" f) ?9 |
智能合约
. K8 A+ v% A, y& ~
4 ?9 G: U& ?4 ~/ k. `+ C' k每个程序员都用他们最喜欢的编程语言执行了一个“hello world”程序,以了解运行该语言的基础知识。这是我们使用 Solidity 语言编写的简单的“hello world”版本的智能合约,我们可以在区块链上添加问候语并检索它。Solidity 是编写智能合约最常用的语言,它编译为可以在节点上运行的以太坊虚拟机上执行的字节码。5 J' Q2 M; Z' J9 ]6 e
, A; i8 V; h2 F8 h
  1. pragma solidity ^0.5.7;
    ' N5 r# t, @; A9 Y/ t( O# W7 K
  2. contract greeter{
    " a; g/ Y+ O2 T) q/ X3 D' J% y, D
  3.     string greeting;9 U8 N! g) S( c$ ?8 G/ _
  4.     function greet(string memory _greeting)public{4 e0 t# I+ O3 W7 ]
  5.         greeting=_greeting;; D. S* @2 w$ N9 @! H
  6.     }
      Y4 T. K# B, Z5 V7 k8 h$ q4 y
  7.     function getGreeting() public view returns(string memory) {, m# M% t) k1 P7 @4 S) Y
  8.         return greeting;! Z2 V4 Z! G- i7 I5 x7 k; D
  9.     }
    5 G2 o- Q( r2 m8 T
  10. }
    3 `. ]5 O. Z- s" Q! N1 j
复制代码

' a! u- T2 `. Y$ L. Y# ]9 O+ K) p# O4 t2 W
您可以通过传递字符串值使用 greet() 方法添加问候语,并使用 getGreting() 方法检索问候语。
% u) l5 i' H& J+ J9 Y: ~0 V* g, g! B% D; d; s! Y
1. 在区块链网络上部署智能合约. Z- [$ U+ i4 n: b1 t& p) ~: Z
# ?! O. t, d. W* k6 R
a) 创建项目:
; }- ]1 @- G6 {- w& U8 A7 B
$ C: B9 Q6 ^. @  Zmkdir pythonDapp
# k! m1 A# W1 ]* n7 Vcd pythonDapp
2 O5 E& w$ a7 e" Gtruffle init4 {- L# P+ u* ?

& q3 X1 R+ K7 Q  u7 @( k/ `' O
; e& n  F  v9 Y, D成功初始化项目后,转到您的文件夹并在 /contracts目录中创建 greeter.sol 文件。在网络上部署合约之前,我们必须编译它并构建工件。
, F2 R! s8 i2 X. |7 y
# d; N- l/ H9 P8 ]9 }b) 智能合约的编译:因此,对于编译,我们将使用 Truffle solc 编译器。在您的主目录中,运行以下命令:
) [' L8 n/ D) V
  F) H( {) a( `7 N& f( g" u7 t! H2 D! Q1 O0 Z6 {" J

/ H1 ]2 [+ J2 [$ b, G+ B. n$ {truffle compile
" J. ~- b5 W- o(or)2 O: [* h, y% W5 |: w1 L
truffle.cmd compile #(for windows only)2 ~9 B# n1 V% y/ \
5 r8 I2 Z' G! R/ a: O
) W( Q4 y  a* r, b2 Y
上面的命令将在 /contracts 目录中编译你的合约,并在 /build 目录中创建二进制工件文件 greeter.json。
' R1 C0 m. z0 W" _, y( a+ F, n- d: c- P
c) 部署合约:打开您的 Python IDLE 编辑器,并在主目录 deploy.py 中使用以下代码创建一个新文件,然后在您的目录中运行 py deploy.py。6 g9 l+ P  y# t& q6 s) m# V. R

* @0 Y4 H& P: d8 x2 J. X0 U
  1. import json
    : {" e& {/ d( {* K) A& ~
  2. from web3 importWeb3, HTTPProvider
    * \$ G+ M# A9 \: ^" W
  3. from web3.contract importConciseContract# {4 T; k) ~" {4 J8 M2 v
  4. # web3.py instance3 H/ F8 a, O7 b
  5. w3 = Web3(HTTPProvider("https://ropsten.infura.io/v3/<API key>"))
    * a  ^/ W) O! r: o$ }
  6. print(w3.isConnected())
    % g" i3 q5 H* D; }
  7. key="<Private Key here with 0x prefix>"" G" b, A, ]3 l
  8. acct = w3.eth.account.privateKeyToAccount(key)* T/ g9 P, ]8 x8 T9 `
  9. # compile your smart contract with truffle first( h- ]2 e8 p1 K' _3 p% ^
  10. truffleFile = json.load(open('./build/contracts/greeter.json')); R/ X( @$ s8 T1 ^! [7 q  A
  11. abi = truffleFile['abi']3 v. @- t) c( S8 q9 k" p4 c, M& M
  12. bytecode = truffleFile['bytecode']+ u7 D# `6 [2 |; L
  13. contract= w3.eth.contract(bytecode=bytecode, abi=abi)" a* O- W# {0 q& V) W
  14. #building transaction3 e) u) A5 |, X- p$ a8 E3 ?
  15. construct_txn = contract.constructor().buildTransaction({+ ^, ~( {' b. y
  16. 'from': acct.address,- I  j" e5 b1 @+ |/ h) z5 |; S2 `# m
  17. 'nonce': w3.eth.getTransactionCount(acct.address),% m3 n5 G9 e1 c- y% D  Z# \3 G
  18. 'gas': 1728712,
    % V" ^2 F5 a) g
  19. 'gasPrice': w3.toWei('21', 'gwei')})9 e- l, q" d8 T: ?+ k- @- E% `
  20. signed = acct.signTransaction(construct_txn); L/ B6 f# S# I: }* [- u
  21. tx_hash=w3.eth.sendRawTransaction(signed.rawTransaction)5 G* H6 m8 r3 l  {% R& @0 ^
  22. print(tx_hash.hex()). t' i4 b$ `& T) Z0 K1 U
  23. tx_receipt = w3.eth.waitForTransactionReceipt(tx_hash)0 p3 D) D+ N0 j/ F$ o+ y
  24. print("Contract Deployed At:", tx_receipt['contractAddress'])
复制代码

/ K7 l, r0 N. J* y* m, ?8 H: C
7 n$ `9 r  R) X# L" \; Q$ ^$ [0 {  s1 e$ ~( ]
这是我所做的:; l9 t' W5 i7 M* Y

, }4 m9 g) k# ]( t1 T8 Q0 U$ v导入的 web3 库和所有其他必需的模块
, I% D1 Z' Y4 l, o通过指向 Ropsten Infura 节点启动 web3 提供程序
  D( v) V! Q. c添加了用于签署交易的帐户地址和私钥。不要忘记在代码中添加您的凭据。
# ^5 y3 U% t1 j; e通过指向 Truffle 编译的工件文件greeter.json的abi和字节码启动合约实例
3 b1 S' Q8 K. @0 K添加了带有随机数、gas、gasPrice 等参数的construct_txn。此处,gas 是指交易应在以太坊中使用和支付的最大计算资源量。gasPrice 是指在交易中使用该数量的 gas 时的最小 Ether 数量。to 指的是您发送交易的地址。仅当您将 Ether 发送到帐户或智能合约时才需要 to 参数。
% d$ c1 R1 O) m使用我们的私钥签署交易并在网络上广播。
, \  ^- Q" V8 ?2 D% N: f* K# U在控制台中记录交易哈希和部署的合约地址。根据以太坊的说法,事务处理时间 <20 秒。所以你必须等待 20 秒才能获得部署的合约地址。您的后端现在已成功部署在以太坊区块链上。现在您可以使用此地址与您的智能合约进行交互。复制此合约地址。( a4 _$ Y. Q3 e& E
2. 向部署的合约发送交易. }) `( b# `: e/ a5 u( g, B1 W

. O+ P: I$ K( H; T( K8 B- \在我们的合约中,有一个方法greet()。我们可以单独使用这种方法在我们的合同中添加问候语。让我们看看我们如何使用 web3.py 来做到这一点。打开您的 Python IDLE 编辑器并使用以下代码创建一个新文件 sign.py。然后在您的目录中运行 py sign.py。
5 ?  R$ M8 Y- z* M1 ^: i8 Y
  1. import json# O8 W! O4 \. |3 w4 c
  2. from web3 importWeb3, HTTPProvider
    , f6 x3 U# F4 w$ \
  3. from web3.contract importConciseContract4 R7 A! t9 e# s# ?% p* p
  4. # compile your smart contract with truffle first
    : ^) |1 a- ^& K
  5. truffleFile = json.load(open('./build/contracts/greeter.json'))/ b4 A0 I% ]2 Q
  6. abi = truffleFile['abi']
    ! S. L+ `% v8 t/ `) G8 V
  7. bytecode = truffleFile['bytecode']* p, y2 c- z# `8 w' S
  8. # web3.py instance
    # K, x9 d: t. |- r( ~( b
  9. w3 = Web3(HTTPProvider("https://ropsten.infura.io/v3/<API key>")) #modify+ U; S; {2 g' j7 @: `0 q
  10. print(w3.isConnected())
    + L$ b" V6 [# l  @& G" S
  11. contract_address = Web3.toChecksumAddress("<Deployed Contract Address here>") #modify
    - B5 s, _' A* m: {- R
  12. key="<Private key with 0x prefix here>"#modify4 `+ w& j1 ~+ R
  13. acct = w3.eth.account.privateKeyToAccount(key)
    - p# V, _3 _( _, B
  14. account_address= acct.address9 O6 X; c% c6 j& h$ n& A7 T
  15. # Instantiate and deploy contract3 f* [+ }4 i8 ]
  16. contract = w3.eth.contract(abi=abi, bytecode=bytecode)
    % Z% B4 r5 ^6 E4 g- m
  17. # Contract instance" ~; l3 J8 U3 }; r* Y0 @
  18. contract_instance = w3.eth.contract(abi=abi, address=contract_address)
    ) g8 i' i4 Z5 a6 W
  19. # Contract instance in concise mode2 v* K7 C+ p" o+ \
  20. #contract_instance = w3.eth.contract(abi=abi, address=contract_address, ContractFactoryClass=ConciseContract)- w: D' f- J/ [7 f9 `9 v5 x( E
  21. tx = contract_instance.functions.greet("Hello all my goody people").buildTransaction({'nonce': w3.eth.getTransactionCount(account_address)})4 p" w1 Z& L* X( h' I- C% w
  22. #Get tx receipt to get contract address
    / j. m$ t# d; O3 |3 I
  23. signed_tx = w3.eth.account.signTransaction(tx, key)+ o0 U2 s. u: x
  24. #tx_receipt = w3.eth.getTransactionReceipt(tx_hash)
    ' i" v9 u( |, l0 q& P
  25. hash= w3.eth.sendRawTransaction(signed_tx.rawTransaction)
    1 X. g! @/ |4 T7 D) G+ ~
  26. print(hash.hex())
复制代码

9 i$ |( l! O3 o) A$ ~; t1 c
5 {/ _" g3 C4 K/ o7 ^+ T0 u: A8 o, e2 \/ s
这是我所做的:
* y$ F  m6 @1 ?# g$ e8 r, i  Z9 A! S! V8 q- V! I; _: C) i6 A
导入的 web3 库和所有其他必需的模块
7 _6 i  H- ?. e  u通过指向 Ropsten Infura 节点启动 web3 提供程序
8 ], ~' Z1 x- _2 X- m% t  j添加了用于签署交易的帐户地址和私钥
7 [/ y8 T' r# U7 D8 `通过指向 Truffle 编译的工件文件greeter.json的abi和字节码启动合约实例) a4 C( k7 }% w9 ~3 D1 y
创建 tx 对象以添加问候语“hello all my goody people”并建立交易0 X% l8 T$ ?/ _  @. p
使用我们的私钥签署交易并在网络上广播。" j5 o0 N: G( C: y5 l$ t2 ~3 L
在控制台中记录交易哈希。您可以使用您的交易哈希在 etherscan 上检查交易状态。一旦交易被矿工验证,我们的问候语将被添加到区块链上。您可以使用 getGreeting() 函数检索问候语,如下所述。6 Y- w1 Q: V2 Q1 L, e% ~/ f6 r
3. 从部署的智能合约中读取数据3 L( Z! M3 l) ^# p* j6 b+ e

% Z2 c# k/ s$ S! ?) V1 R) B在我们的合约中,有一个方法 getGreeting() 可以检索我们在区块链中添加的问候语。我们将使用 web3.py 调用此方法 打开您的 Python IDLE 编辑器并使用以下代码创建一个新文件 read.py。运行 py read.py 读取问候语。0 j7 c% P7 @: D- x- e  ]
  1. ' Z+ N# P' z- E; [, q1 P' e
  2. import json; f$ c3 E3 ~, C% |8 j
  3. from web3 importWeb3, HTTPProvider
    4 [+ `2 D6 r# x! c; M1 q
  4. from web3.contract importConciseContract* n) y3 B5 O  [' ]; [2 f
  5. # compile your smart contract with truffle first$ _) O% |3 g8 V6 ?* k7 y
  6. truffleFile = json.load(open('./build/contracts/greeter.json')). @8 B# J' z0 {0 \4 j" W
  7. abi = truffleFile['abi']0 b6 d7 W3 B4 }0 ?9 h% O7 K
  8. bytecode = truffleFile['bytecode']
    # m: l( `# c( C$ f* X: p
  9. # web3.py instance0 g+ ?' \8 l6 d( S  [! C. \
  10. w3 = Web3(HTTPProvider("https://ropsten.infura.io/<ApI Key here>"))
    ) U, |; m! f2 n* A' f/ z* A
  11. print(w3.isConnected())
    . T1 Y- q! v2 A3 G* b7 W" b# h
  12. contract_address = Web3.toChecksumAddress("<Deployed Contract Address here>"). Q. D: _" t- E1 n/ L8 T- T
  13. # Instantiate and deploy contract
    9 y3 P3 z) A: m1 r
  14. contract = w3.eth.contract(abi=abi, bytecode=bytecode)
    ) T1 K: S* D5 M# U+ @: M! x
  15. # Contract instance
    " A4 h/ P; y) m  n( |1 L# S
  16. contract_instance = w3.eth.contract(abi=abi, address=contract_address)
    * |* Z& [% A& Q
  17. # Contract instance in concise mode$ F& y4 Z# Z1 b, }+ d! R7 a+ y9 e
  18. #contract_instance = w3.eth.contract(abi=abi, address=contract_address, ContractFactoryClass=ConciseContract)
    9 ^% t; v9 p- h- t+ w1 z' o
  19. # Getters + Setters for web3.eth.contract object ConciseContract
    8 \* h7 G1 x. C( c
  20. #print(format(contract_instance.getGreeting()))
    " }  J$ F, G' }0 o! F: H8 r
  21. print('Contract value: {}'.format(contract_instance.functions.getGreeting().call()))
复制代码

2 }% b! }% A/ f" z" {7 u  w0 w; |- v
" I$ B* U  a( T) U# H) o
这是我所做的:
+ w; w" b  d; L9 X4 O: G+ p; v& Z/ ^$ S' i
导入的 web3 库和所有其他必需的模块
; E  T. w# Q) q7 D; \2 k通过指向 Ropsten Infura 节点启动 web3 提供程序* n/ b- M3 e/ W+ u; a( `
通过指向 abi 和 contract_Address 创建合约实例(来自上一步)
6 H3 h) ~2 i$ ?& E* e/ ~9 m调用 getGreeting() 方法并在控制台打印结果% Q' k7 [9 W2 v7 M7 W. k
结论, Q5 j$ E4 U, v/ J

( \5 I+ x2 \/ T0 w* ]" w您现在应该了解如何使用 web3.py 部署、交互和签署交易。让我们通过查看我使用 web3.py 创建的实时 DApp 并在此处使用 Flask 作为前端服务器来将所有部分组合在一起。它将帮助您更深入地了解使用 Python 进行 DApp 开发。
2 i  p+ N0 x; x$ {  y$ F8 V5 j, _: s/ ?% ?; d
0 G/ {, c1 U& ]2 l! V* o
参考 @温室小书生室dpython利用web3.py开发以太坊应用dapp的实战教程
  d+ E3 [* v% @8 E, O0 T- v( q  e
标签: Python Python Python
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

常德小学生 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    13