Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

用 Python 中的 web3.py 库开发 Dapp

常德小学生
3163 1 0
什么是 DApp  ^1 e0 j6 D* w/ ]
( I. w+ O$ \& D$ {3 F
“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 库与区块链进行交互。
$ e2 i) Q" N& l# K0 o, W, n. @! K2 L! i) L( e9 P. V( _7 y
Dapps 开发包括三个简单的步骤:0 ]3 r# g0 z( ?) \4 y1 T5 F
  • 在区块链网络上部署智能合约
  • 从部署的智能合约中读取数据
  • 将交易发送到部署的智能合约; q" ~- n; ]- W  k3 Y9 s& ?
我们将在带有 web3.py 库的 python 环境中一步一步地进行这三个操作要与区块链交互,我们必须连接到任何完全同步的节点。在本教程中,我们指向一个 Infura 节点。确保你有一个以太坊钱包(使用 Metamask chrome 扩展或 myetherwallet 创建以太坊钱包并安全地存储你的私钥)并在其中添加一些测试 Ether 以进行操作。/ ^) g0 _' G( c' j' y
* g  A+ l1 V2 T/ d
安装
" r% h/ G/ g. ?+ R* ]9 g1 `) v$ a/ w, j+ @) r* w: Q
Python 2.7 +
; u9 `* |& B5 i0 F- eNode.js1 ]* r$ {. K8 j" T
Truffle
1 {/ g# u/ b' r/ g
1 y' J5 n# M, P% y: I, M1 t8 i$ F6 X+ e7 F/ ~2 o- V
npm install -g truffle( a4 _0 r  H2 u) T, V, g! I' ?
Pip
: K9 u9 j9 J1 b  I9 ]npm i pip
; z) |; K8 [- P) n% g# e( t! [web3.py* J) n; i" k* _: w# E+ x2 o
pip install web3) m/ N% H$ N% y. x4 j9 X3 F5 _
: L$ k3 C  H% @: T8 H; L

* ?' [) T4 X8 YInfura 项目 API# K6 b0 F6 B& k$ @' ?
前往 Infura 网站并注册。创建一个新项目并复制 Ropsten Infura RPC URL。我们将把我们的智能合约部署到 Ropsten 测试网络。
6 ^5 f" S/ D  Y2 t5 b3 ~* r3 B5 d8 f0 o6 n
% n$ x8 J/ [" @+ z; n+ S9 l) B智能合约
+ ]7 _/ M. |9 M. i% |2 _) g3 {4 f3 N) J
每个程序员都用他们最喜欢的编程语言执行了一个“hello world”程序,以了解运行该语言的基础知识。这是我们使用 Solidity 语言编写的简单的“hello world”版本的智能合约,我们可以在区块链上添加问候语并检索它。Solidity 是编写智能合约最常用的语言,它编译为可以在节点上运行的以太坊虚拟机上执行的字节码。
6 L+ z( a. @( `, Z1 V, }$ {; X, S: N
  1. pragma solidity ^0.5.7;
    " M7 c2 Y% K$ P; I
  2. contract greeter{& ?' }7 M0 l" C+ s3 I4 o% y/ i
  3.     string greeting;. @; u: b, M* a$ |4 D
  4.     function greet(string memory _greeting)public{
    : \2 U  y$ \" {/ e& A2 z: W; a
  5.         greeting=_greeting;
    & _. S9 m7 r% ~
  6.     }
    1 ^9 O* G+ y3 t, o9 w$ w# o
  7.     function getGreeting() public view returns(string memory) {
    * f' {6 Q1 D8 ?: @, F* |
  8.         return greeting;! F' T$ F4 H5 W4 H- w% a: K
  9.     }
    2 R2 S$ l7 \8 l5 B5 C
  10. }
    9 h5 }6 k1 C3 v
复制代码
* ]/ S/ P  n2 ]1 \6 n
$ _. [+ m- k) }1 o; d1 v: O
您可以通过传递字符串值使用 greet() 方法添加问候语,并使用 getGreting() 方法检索问候语。( y, |3 K5 r, R% C
$ o; J+ X9 Z- b7 R: K5 c
1. 在区块链网络上部署智能合约: c0 S+ {/ k) t- Y
1 i. E. g/ P- f9 ~/ `+ U  y
a) 创建项目:, p" o# h% O* j6 x  c! f

; E1 m! \* D9 l, ^mkdir pythonDapp
1 U7 `. Q3 c9 A$ j5 j# t1 Mcd pythonDapp. J7 p1 Z; `3 F) S# l4 ^/ f
truffle init
. A. B1 Z2 L& K- S) Q$ Q1 r& b4 l
" m4 b2 t: j4 J3 V; s' O1 {+ ]* }4 N% S8 P0 i# C, _
成功初始化项目后,转到您的文件夹并在 /contracts目录中创建 greeter.sol 文件。在网络上部署合约之前,我们必须编译它并构建工件。
- r0 Q5 C) P, w; E- G4 d, v% I2 b3 D5 o
b) 智能合约的编译:因此,对于编译,我们将使用 Truffle solc 编译器。在您的主目录中,运行以下命令:$ R! G2 }- \/ l" ^4 H' V0 b! ~3 ^: m0 _
9 ~5 z. K4 a9 O3 C1 r4 Y
1 D0 E+ ^" H4 t& b$ u  ^

2 Y% u2 J: b) X5 struffle compile- a; v- g8 @* a; z
(or)4 Z, \: L1 Q; l
truffle.cmd compile #(for windows only)& f9 t( u+ {5 b+ M0 ?, @

% B" }! {: L* F1 O0 }6 }$ s& K+ E
上面的命令将在 /contracts 目录中编译你的合约,并在 /build 目录中创建二进制工件文件 greeter.json。% j; g$ |2 V2 F4 s: f% k; F7 t

7 s2 C& E2 l! {, X. dc) 部署合约:打开您的 Python IDLE 编辑器,并在主目录 deploy.py 中使用以下代码创建一个新文件,然后在您的目录中运行 py deploy.py。) Q- C7 t* |& U" Q; B9 l' _  P
3 L7 B' r/ U( K) [: f3 u
  1. import json
    ; W4 v  j7 l- I  C5 R, D$ |
  2. from web3 importWeb3, HTTPProvider
    # @8 x( O  n/ j: T3 d: N' b* |: j
  3. from web3.contract importConciseContract! \* ]6 i+ S& a: V% L, p7 S( ^5 e
  4. # web3.py instance
    ) M0 N& Z, I, I3 Z
  5. w3 = Web3(HTTPProvider("https://ropsten.infura.io/v3/<API key>"))2 Y) D! K( l, k4 J, r1 z4 ^+ |
  6. print(w3.isConnected())
    $ {. |. _. A7 G4 U; c
  7. key="<Private Key here with 0x prefix>"
    $ ^( b, r$ ^$ Q8 v9 X( K
  8. acct = w3.eth.account.privateKeyToAccount(key)
    ' f6 j# u+ \! ]7 g
  9. # compile your smart contract with truffle first
    ( z) R0 [4 [2 f0 d( s0 U+ N& p
  10. truffleFile = json.load(open('./build/contracts/greeter.json'))
    3 }( V. V9 v9 v8 R% _  Y, V' a
  11. abi = truffleFile['abi']* j8 Z& c$ ?* q4 z/ L
  12. bytecode = truffleFile['bytecode']
    ' E  c/ L9 w  E3 F" C
  13. contract= w3.eth.contract(bytecode=bytecode, abi=abi)) w/ g) `7 _* S& Y! r) i+ t! x6 e
  14. #building transaction" h+ k* F5 c' J9 p3 ?  x$ N
  15. construct_txn = contract.constructor().buildTransaction({
    4 u) U1 ^' ]/ z  ^9 y/ q% Q
  16. 'from': acct.address,
    " C/ F2 W- S( H2 _: f& G2 X
  17. 'nonce': w3.eth.getTransactionCount(acct.address),, }3 u7 o4 O+ p+ C" l2 h
  18. 'gas': 1728712,
    2 D/ r4 l# z+ J9 G. J% M+ c
  19. 'gasPrice': w3.toWei('21', 'gwei')})' I. N& [# c# x
  20. signed = acct.signTransaction(construct_txn)
    ' b9 ?/ J5 n/ S
  21. tx_hash=w3.eth.sendRawTransaction(signed.rawTransaction)
    5 i3 w7 s" i7 d( }3 m' ?
  22. print(tx_hash.hex())" I3 P3 i" A/ o/ @4 C" C% D- i
  23. tx_receipt = w3.eth.waitForTransactionReceipt(tx_hash)
    , \5 S" ^6 p& ?: P9 y  s* ]9 S( P& Y( a
  24. print("Contract Deployed At:", tx_receipt['contractAddress'])
复制代码

$ F0 Q: X7 t/ p; Z% N, S5 u: v; C
- P5 I$ t' \  ]& A4 x
这是我所做的:
8 P1 c3 ]4 ?, ]3 q, {) g
$ y% l8 Y: r0 Y" X7 A0 P; Y9 a8 A, G导入的 web3 库和所有其他必需的模块5 V0 P/ N& {5 B( Y5 V8 U! v
通过指向 Ropsten Infura 节点启动 web3 提供程序- U# E6 `+ ^1 J9 L3 z$ e% ^
添加了用于签署交易的帐户地址和私钥。不要忘记在代码中添加您的凭据。
* y( j* T& U/ \' o通过指向 Truffle 编译的工件文件greeter.json的abi和字节码启动合约实例5 v0 m. J# ]3 e2 |! \  b8 N
添加了带有随机数、gas、gasPrice 等参数的construct_txn。此处,gas 是指交易应在以太坊中使用和支付的最大计算资源量。gasPrice 是指在交易中使用该数量的 gas 时的最小 Ether 数量。to 指的是您发送交易的地址。仅当您将 Ether 发送到帐户或智能合约时才需要 to 参数。. z6 C, Q9 h6 p! e; [. w7 M& M
使用我们的私钥签署交易并在网络上广播。
' K/ `- V% j+ s$ `- J, @* }. x在控制台中记录交易哈希和部署的合约地址。根据以太坊的说法,事务处理时间 <20 秒。所以你必须等待 20 秒才能获得部署的合约地址。您的后端现在已成功部署在以太坊区块链上。现在您可以使用此地址与您的智能合约进行交互。复制此合约地址。
' V& O4 J5 |$ S# u* X& e* `8 _2. 向部署的合约发送交易
5 C) a" g. A3 f, @- Z$ s+ \
- E4 i4 Y1 O8 ~" M7 s0 ?在我们的合约中,有一个方法greet()。我们可以单独使用这种方法在我们的合同中添加问候语。让我们看看我们如何使用 web3.py 来做到这一点。打开您的 Python IDLE 编辑器并使用以下代码创建一个新文件 sign.py。然后在您的目录中运行 py sign.py。" W/ q( k( e$ B1 Y4 S1 P
  1. import json
    ' N2 I8 \' P/ _& A* i6 w+ K* M6 w
  2. from web3 importWeb3, HTTPProvider& {" D- j5 y. i" [. q' \" l
  3. from web3.contract importConciseContract1 h  T; v' p5 e$ R) V
  4. # compile your smart contract with truffle first
      c  J5 I! O; `  C' O; v" `) ~: d& ~
  5. truffleFile = json.load(open('./build/contracts/greeter.json'))
    * e7 X! f2 m/ A8 o6 T% G! i  W
  6. abi = truffleFile['abi']4 _0 W  ^5 U9 V. o4 F
  7. bytecode = truffleFile['bytecode']
    ) Z0 F2 E+ S2 X: j& J- `: n/ H  p# g" ?' r
  8. # web3.py instance
    7 D1 t% ~9 Z6 D. P/ x3 G9 }& b0 ?
  9. w3 = Web3(HTTPProvider("https://ropsten.infura.io/v3/<API key>")) #modify
    ! R. d7 x5 {" `8 U, R# W/ y
  10. print(w3.isConnected())
    4 L1 ^! h! z1 c* P
  11. contract_address = Web3.toChecksumAddress("<Deployed Contract Address here>") #modify
    . o& G. v, E: S
  12. key="<Private key with 0x prefix here>"#modify
    4 _( ~4 F( E; I- V1 X
  13. acct = w3.eth.account.privateKeyToAccount(key)
    5 E0 D$ V2 j4 j: \- ?7 ^- j1 S
  14. account_address= acct.address3 x9 D! c' h+ R6 \1 H
  15. # Instantiate and deploy contract- t  B0 R+ k8 [' P1 K! Q- h3 I
  16. contract = w3.eth.contract(abi=abi, bytecode=bytecode)6 l* Z/ i6 K" X# ^
  17. # Contract instance" U2 N( W5 W* Q4 v  h
  18. contract_instance = w3.eth.contract(abi=abi, address=contract_address)
    + [" F: o+ t0 K& @5 }# {+ K( |7 N
  19. # Contract instance in concise mode, |# G) i  r: Y) C& _
  20. #contract_instance = w3.eth.contract(abi=abi, address=contract_address, ContractFactoryClass=ConciseContract)
    9 C/ S% f+ d' Y& V, z2 i
  21. tx = contract_instance.functions.greet("Hello all my goody people").buildTransaction({'nonce': w3.eth.getTransactionCount(account_address)})
    & T2 [6 t. Z' @! N9 v* E
  22. #Get tx receipt to get contract address
    4 C7 ^5 A% ]' V' j" ^0 K
  23. signed_tx = w3.eth.account.signTransaction(tx, key)
    0 ?, b+ k" Z9 E& M: n- V- d. \
  24. #tx_receipt = w3.eth.getTransactionReceipt(tx_hash)6 ]9 I, }; t7 K$ j: h
  25. hash= w3.eth.sendRawTransaction(signed_tx.rawTransaction)$ N, E( o% z5 S
  26. print(hash.hex())
复制代码
: T, k, y1 {/ c- S

. u" m; s. I# T+ n
& E  I" a- p( ?7 Y这是我所做的:* v' ~3 L$ k/ A8 ^! n7 T

& A$ q, K( `2 ~3 Y导入的 web3 库和所有其他必需的模块5 }* k) t3 c  K" l3 M
通过指向 Ropsten Infura 节点启动 web3 提供程序
5 q1 G5 x0 y+ Q% F% B4 `' Q添加了用于签署交易的帐户地址和私钥9 u5 p5 u) c4 ^& t) [
通过指向 Truffle 编译的工件文件greeter.json的abi和字节码启动合约实例1 R5 B* {* Z" I. \- r) n/ y
创建 tx 对象以添加问候语“hello all my goody people”并建立交易4 H" K: O/ s) N+ U2 G$ _; @
使用我们的私钥签署交易并在网络上广播。
% W1 r2 Y6 q0 {" [1 _9 Z在控制台中记录交易哈希。您可以使用您的交易哈希在 etherscan 上检查交易状态。一旦交易被矿工验证,我们的问候语将被添加到区块链上。您可以使用 getGreeting() 函数检索问候语,如下所述。
* W& c! [( ^5 [7 C3. 从部署的智能合约中读取数据
- l% J0 u+ S. h; y" y5 p  _& i" z( r- c# r  g+ |
在我们的合约中,有一个方法 getGreeting() 可以检索我们在区块链中添加的问候语。我们将使用 web3.py 调用此方法 打开您的 Python IDLE 编辑器并使用以下代码创建一个新文件 read.py。运行 py read.py 读取问候语。
9 x7 O2 B& w5 @' u- h; B

  1. 9 r8 I! s# H4 N% z( u
  2. import json
    5 C+ W8 O( j- }
  3. from web3 importWeb3, HTTPProvider
    ! p0 `& x9 u" |5 `% {% ^/ J
  4. from web3.contract importConciseContract
    0 d9 G# q! _6 e; s( Z- X
  5. # compile your smart contract with truffle first
    + j4 K" Q( f9 F
  6. truffleFile = json.load(open('./build/contracts/greeter.json'))
    3 {3 _$ @3 [( _" N
  7. abi = truffleFile['abi']$ ?2 ]. S7 z  `' O$ k( |+ e
  8. bytecode = truffleFile['bytecode']
    ' A  e" h+ ^* J# [: m1 _* {
  9. # web3.py instance8 a6 z6 Q! L1 P$ D' }
  10. w3 = Web3(HTTPProvider("https://ropsten.infura.io/<ApI Key here>"))
    . j! y7 ~6 b* T$ J3 o6 f; v
  11. print(w3.isConnected())# l. E; p& r$ D" {
  12. contract_address = Web3.toChecksumAddress("<Deployed Contract Address here>")+ \8 `8 T- o4 C$ [# e$ g- g
  13. # Instantiate and deploy contract) u9 B! {* _2 G2 ]# B9 k
  14. contract = w3.eth.contract(abi=abi, bytecode=bytecode)
    0 V- b* h; ~6 ~1 T7 C1 L  Y& }
  15. # Contract instance
    , u$ v2 D3 B# C9 s% u+ T
  16. contract_instance = w3.eth.contract(abi=abi, address=contract_address)% D5 Q4 U5 V5 [& Z2 q
  17. # Contract instance in concise mode# v  y$ N- x+ F4 a4 P& \0 l- t8 |
  18. #contract_instance = w3.eth.contract(abi=abi, address=contract_address, ContractFactoryClass=ConciseContract)! y; t: r1 Z/ L- Y  b- T7 m
  19. # Getters + Setters for web3.eth.contract object ConciseContract
    - c% s, o1 G: [
  20. #print(format(contract_instance.getGreeting()))+ R( v" X! l. g4 \" V8 v& h4 {% V) C
  21. print('Contract value: {}'.format(contract_instance.functions.getGreeting().call()))
复制代码
, x: }+ j& H# `! K# I2 y

0 |9 w3 \9 m/ k' o% R* W! J* i# v; a2 C" _
这是我所做的:6 l+ C5 ]  I' D% U

: U3 [# u8 u: ?2 F0 j导入的 web3 库和所有其他必需的模块) b- u3 `) M3 C
通过指向 Ropsten Infura 节点启动 web3 提供程序, n" [- [2 p1 y) \! R
通过指向 abi 和 contract_Address 创建合约实例(来自上一步)
. s0 `1 l" h7 W. ]调用 getGreeting() 方法并在控制台打印结果7 q: C- n7 U. K; O. M% v2 h
结论
- e9 ~% g& t. W$ `& X" R$ {: r5 n* Y- ^( ?' _
您现在应该了解如何使用 web3.py 部署、交互和签署交易。让我们通过查看我使用 web3.py 创建的实时 DApp 并在此处使用 Flask 作为前端服务器来将所有部分组合在一起。它将帮助您更深入地了解使用 Python 进行 DApp 开发。
, Z* R- S# q$ ]* x! i2 a  {
8 C7 q4 U3 b* C( c" [( W
3 h0 |0 [, M6 N: ~0 ?: `4 p8 j+ d参考 @温室小书生室dpython利用web3.py开发以太坊应用dapp的实战教程
* ]7 X1 _0 o& Z# J" S" @7 H
标签: Python Python Python
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

常德小学生 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    13