Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

用 Python 中的 web3.py 库开发 Dapp

常德小学生
2376 1 0
什么是 DApp
) x; B1 d! T) f
. I/ z  @: `9 F! ?2 ?“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 库与区块链进行交互。0 a# e% D. s! t% {
# U# t. N% U8 g: n  P. J
Dapps 开发包括三个简单的步骤:
$ a& b& T% E; V3 m" ?7 e; i
  • 在区块链网络上部署智能合约
  • 从部署的智能合约中读取数据
  • 将交易发送到部署的智能合约- p, i$ i0 |4 n3 {! i
我们将在带有 web3.py 库的 python 环境中一步一步地进行这三个操作要与区块链交互,我们必须连接到任何完全同步的节点。在本教程中,我们指向一个 Infura 节点。确保你有一个以太坊钱包(使用 Metamask chrome 扩展或 myetherwallet 创建以太坊钱包并安全地存储你的私钥)并在其中添加一些测试 Ether 以进行操作。
; I5 b% u1 O$ v  s* h) P- q
* q# Q9 }( J- ^+ v' m4 l安装( f1 @- D6 d2 k5 U6 ?/ V. m" s

& r1 L- M& R% p! n& _; kPython 2.7 +/ \. g8 N6 B9 n8 w3 m
Node.js+ C. B" L" ^3 L8 @( Q$ F: B
Truffle' U  Y: R- }% I8 {) @
. u! i1 O. s) k0 \" {

+ p9 {! z5 B( i8 ?3 w' ^npm install -g truffle* h3 }9 P9 R6 f
Pip! q& ~8 `7 u% M" u
npm i pip
' {. Y4 D8 w. g0 f/ Tweb3.py; `$ l7 w' ]. u
pip install web33 L- H9 m& s# m' j5 d  |1 P- M% ^
' V7 C/ j1 a! Y

* x5 L( f3 f0 [  z/ YInfura 项目 API2 t$ V% r; ?; x
前往 Infura 网站并注册。创建一个新项目并复制 Ropsten Infura RPC URL。我们将把我们的智能合约部署到 Ropsten 测试网络。
7 G* s; ]* z0 C' W
# F7 W8 `7 W( X7 F& K/ g8 j7 G7 m智能合约5 n& y" a1 K/ Y- H# |2 w$ @4 z
5 @  x3 v+ w' w  X* t- g
每个程序员都用他们最喜欢的编程语言执行了一个“hello world”程序,以了解运行该语言的基础知识。这是我们使用 Solidity 语言编写的简单的“hello world”版本的智能合约,我们可以在区块链上添加问候语并检索它。Solidity 是编写智能合约最常用的语言,它编译为可以在节点上运行的以太坊虚拟机上执行的字节码。# x: a# p+ v; w8 y/ V& Q+ a3 M$ A; D
5 {1 V  |  |$ t
  1. pragma solidity ^0.5.7;- A! [0 i/ ^8 W5 a- ]$ l7 y0 Y) u
  2. contract greeter{' i" L# G5 n1 p+ D+ K
  3.     string greeting;
    ! h0 H0 K8 U: g7 e. D3 c
  4.     function greet(string memory _greeting)public{
    # m5 T+ \$ T4 V' ~7 k8 i- \
  5.         greeting=_greeting;
    ; i# S* k+ r" P- n  x/ p0 {
  6.     }5 n; K6 r3 f- z6 l/ l& A
  7.     function getGreeting() public view returns(string memory) {. w1 `# C, j8 y% M
  8.         return greeting;- g8 x$ n3 I& f7 z; Z- \
  9.     }
    # K  ~, s; F) u
  10. }6 i7 I$ u" f3 q7 N
复制代码
9 X& h( Z9 v5 |* `( D

: c# R8 m  F0 N2 Y0 K0 w0 l您可以通过传递字符串值使用 greet() 方法添加问候语,并使用 getGreting() 方法检索问候语。
* A9 q; r) k  @: t# E  t3 F
& j3 R" n1 c$ D9 B! ]1. 在区块链网络上部署智能合约
. z0 r3 R/ _; I4 j% v& S& F8 w9 N' B! P: _
a) 创建项目:# h) T2 N$ U. k5 y' @" G

3 h' J. Y' B$ g; amkdir pythonDapp: E, D0 W9 Q5 i0 S9 n
cd pythonDapp0 s6 q' O) W8 _% A2 W
truffle init& p7 I7 Z. k& M) R/ `# v
1 w" L' Y1 x7 Q) C% I$ ?

  Z$ b1 h5 L% ?) j成功初始化项目后,转到您的文件夹并在 /contracts目录中创建 greeter.sol 文件。在网络上部署合约之前,我们必须编译它并构建工件。$ T4 {1 Y$ J4 R3 O

( h/ g, ~+ C8 g% sb) 智能合约的编译:因此,对于编译,我们将使用 Truffle solc 编译器。在您的主目录中,运行以下命令:5 p  d$ N1 c% d* A) |

; N8 M$ u( W& V0 P; d6 M! a: q) m& G2 W, v# G
# O8 m; j# k# F: `' p
truffle compile$ O! A: G$ J' ^" Y+ }1 {+ F
(or)2 L% s# v7 K- }1 r4 X3 g: R
truffle.cmd compile #(for windows only)8 A1 S9 U' O" C' J1 k, P( l
3 X# ~; q$ L& h# T7 u
: j6 b' o; b/ F) o9 C* D/ G# {
上面的命令将在 /contracts 目录中编译你的合约,并在 /build 目录中创建二进制工件文件 greeter.json。
! z) s/ u- v6 L0 u+ `/ X& N
; z5 n- l5 d/ u% x0 n; gc) 部署合约:打开您的 Python IDLE 编辑器,并在主目录 deploy.py 中使用以下代码创建一个新文件,然后在您的目录中运行 py deploy.py。
1 v0 a/ @  r& I0 G  O! v3 U- l/ C6 s4 a  ~2 Y, ~1 B3 N
  1. import json
    + @4 u# \- A/ W/ Z/ L% {" N- g- v  C
  2. from web3 importWeb3, HTTPProvider
      x7 H; p' o1 F
  3. from web3.contract importConciseContract* o' t6 [/ G' p( c
  4. # web3.py instance
    8 s3 M6 W; k7 ?7 Z/ c4 L
  5. w3 = Web3(HTTPProvider("https://ropsten.infura.io/v3/<API key>"))
    , U  r" [! ^* T
  6. print(w3.isConnected())# g! c) J! N  o
  7. key="<Private Key here with 0x prefix>"+ m1 T9 Q6 j% _! k, ^: c4 U- g
  8. acct = w3.eth.account.privateKeyToAccount(key)
    3 s  u! L% c& m2 F6 o# n
  9. # compile your smart contract with truffle first
    # P8 j- ~4 l5 {. S: @' }% f
  10. truffleFile = json.load(open('./build/contracts/greeter.json'))
    / z; P! Q* }% \3 A5 N
  11. abi = truffleFile['abi']
    6 r8 b, E, z$ s7 _6 N& ]/ e) A
  12. bytecode = truffleFile['bytecode']! A; n% C0 V7 {8 J7 K) `8 o
  13. contract= w3.eth.contract(bytecode=bytecode, abi=abi)' K. A$ M1 D: B! f" t2 ]: G- Y
  14. #building transaction) @# T6 M0 Z& G: \+ I
  15. construct_txn = contract.constructor().buildTransaction({& @2 J  h2 ]+ C! v
  16. 'from': acct.address,$ `8 T* T5 K% u
  17. 'nonce': w3.eth.getTransactionCount(acct.address),
    2 b0 a3 B: V2 ]
  18. 'gas': 1728712,! r* D- y2 o+ {  D2 ?# A
  19. 'gasPrice': w3.toWei('21', 'gwei')})1 n3 W- q9 N0 \; h% d" O
  20. signed = acct.signTransaction(construct_txn)6 t3 F8 S) y* E* Z: b( B  U/ c
  21. tx_hash=w3.eth.sendRawTransaction(signed.rawTransaction)
    0 S" G7 x$ }& U9 E# s" _
  22. print(tx_hash.hex())0 j  f2 V3 |% i; m" I, Z8 {
  23. tx_receipt = w3.eth.waitForTransactionReceipt(tx_hash)' t/ U7 a( p. ^5 j# o9 y. u
  24. print("Contract Deployed At:", tx_receipt['contractAddress'])
复制代码
3 Q8 \  B, |/ D
3 ^8 A/ b# E6 |# l2 I/ [3 a- t

, Z) V/ E- F1 V% k3 ~5 I' r这是我所做的:
- ^2 f. E+ T2 x$ d$ P- N# ]
% f0 m) u/ H3 ~4 n导入的 web3 库和所有其他必需的模块
+ t, \* ?& T  \. T4 I3 T通过指向 Ropsten Infura 节点启动 web3 提供程序
# ]$ j3 r2 f; B) t7 ~添加了用于签署交易的帐户地址和私钥。不要忘记在代码中添加您的凭据。5 W+ m; E  N/ I4 L$ m% \$ r
通过指向 Truffle 编译的工件文件greeter.json的abi和字节码启动合约实例/ l8 C, \: u) {  K
添加了带有随机数、gas、gasPrice 等参数的construct_txn。此处,gas 是指交易应在以太坊中使用和支付的最大计算资源量。gasPrice 是指在交易中使用该数量的 gas 时的最小 Ether 数量。to 指的是您发送交易的地址。仅当您将 Ether 发送到帐户或智能合约时才需要 to 参数。
. a. @$ k- |& `. K6 F" E使用我们的私钥签署交易并在网络上广播。  E! A9 S' z, N
在控制台中记录交易哈希和部署的合约地址。根据以太坊的说法,事务处理时间 <20 秒。所以你必须等待 20 秒才能获得部署的合约地址。您的后端现在已成功部署在以太坊区块链上。现在您可以使用此地址与您的智能合约进行交互。复制此合约地址。
. ?, v2 q. U! j; v8 q6 v4 p2 f2. 向部署的合约发送交易6 I0 m- B0 |& j# `
, p, v" E3 Q8 j3 ^$ A4 \- ?
在我们的合约中,有一个方法greet()。我们可以单独使用这种方法在我们的合同中添加问候语。让我们看看我们如何使用 web3.py 来做到这一点。打开您的 Python IDLE 编辑器并使用以下代码创建一个新文件 sign.py。然后在您的目录中运行 py sign.py。; H, m8 v9 t; Y  y- b* ]$ Z2 k2 x
  1. import json
    1 i2 e9 a4 N5 l' x# U
  2. from web3 importWeb3, HTTPProvider
    ' ~! I+ ~! D4 W
  3. from web3.contract importConciseContract/ [9 s5 Y: x, ]1 j6 y8 |& f
  4. # compile your smart contract with truffle first
    2 B, a7 ?8 q  g  E8 `' F; q) d( ^
  5. truffleFile = json.load(open('./build/contracts/greeter.json'))8 n2 K& ~" u& w- N' N& u/ T% F
  6. abi = truffleFile['abi']
    ) O8 ~+ A+ }: D8 E  I7 h2 n: V# s; `
  7. bytecode = truffleFile['bytecode']# Z/ R9 |6 ^" ~! F  C
  8. # web3.py instance. \/ \6 E8 ], V2 \
  9. w3 = Web3(HTTPProvider("https://ropsten.infura.io/v3/<API key>")) #modify9 p3 @/ U+ Y, [. A/ {
  10. print(w3.isConnected())0 [8 P" B5 l6 |0 }" f
  11. contract_address = Web3.toChecksumAddress("<Deployed Contract Address here>") #modify
    . `1 }  f; f* `9 v, @9 z
  12. key="<Private key with 0x prefix here>"#modify
    ( L3 M, ^. K1 v9 X, o
  13. acct = w3.eth.account.privateKeyToAccount(key)
    6 p5 Y* ]" |+ N
  14. account_address= acct.address& F2 |2 W/ t8 c0 D5 H, E6 H
  15. # Instantiate and deploy contract- C. k: m' E- |5 N- b4 j. A9 `9 o
  16. contract = w3.eth.contract(abi=abi, bytecode=bytecode)
    # y1 F) e! d) w- I# R
  17. # Contract instance& i2 c* ~7 S  O( Y6 L# D; ?
  18. contract_instance = w3.eth.contract(abi=abi, address=contract_address)! R0 u) N6 S' b8 ~$ Y) H; _/ ]: m
  19. # Contract instance in concise mode
    % p3 @6 g/ N0 t4 O) |
  20. #contract_instance = w3.eth.contract(abi=abi, address=contract_address, ContractFactoryClass=ConciseContract), i, Q: e; y% O; p: W
  21. tx = contract_instance.functions.greet("Hello all my goody people").buildTransaction({'nonce': w3.eth.getTransactionCount(account_address)})
    : z* {" L- `$ p
  22. #Get tx receipt to get contract address7 C# u+ r6 X1 s$ P$ {
  23. signed_tx = w3.eth.account.signTransaction(tx, key)8 V2 h9 M# S% k  G% v
  24. #tx_receipt = w3.eth.getTransactionReceipt(tx_hash)
    5 Z( U/ T5 Y! \+ [: F7 G6 k  F/ C
  25. hash= w3.eth.sendRawTransaction(signed_tx.rawTransaction)/ S, z4 \  [. M/ H" @( A, j$ ]' K
  26. print(hash.hex())
复制代码

* v# ^9 P' f' o" s* z5 v4 o7 x3 Z. D3 F& m6 ?/ z
& z2 x6 _9 ^5 I, Q$ ^7 q8 f
这是我所做的:
, a- o0 J  P; Z0 H0 K% \( h8 I' _2 B+ r: M7 X9 o, R6 R
导入的 web3 库和所有其他必需的模块
$ y3 ?- u& D" v& n* N4 K; ?通过指向 Ropsten Infura 节点启动 web3 提供程序2 |2 A* r$ d7 I8 J
添加了用于签署交易的帐户地址和私钥7 s! V' g4 g* h6 ?) _$ p4 t
通过指向 Truffle 编译的工件文件greeter.json的abi和字节码启动合约实例* o" T7 ]7 o: K
创建 tx 对象以添加问候语“hello all my goody people”并建立交易
  J& v  d2 ~/ S7 l& I( t8 l* {使用我们的私钥签署交易并在网络上广播。
2 q# a2 j" Q! p2 U3 k在控制台中记录交易哈希。您可以使用您的交易哈希在 etherscan 上检查交易状态。一旦交易被矿工验证,我们的问候语将被添加到区块链上。您可以使用 getGreeting() 函数检索问候语,如下所述。" l8 j; u+ G( A% k9 f
3. 从部署的智能合约中读取数据
0 ?3 b( r3 j- y9 O# G8 e" o( Q5 n6 p" f# l4 H
在我们的合约中,有一个方法 getGreeting() 可以检索我们在区块链中添加的问候语。我们将使用 web3.py 调用此方法 打开您的 Python IDLE 编辑器并使用以下代码创建一个新文件 read.py。运行 py read.py 读取问候语。
* [1 b; A5 G6 C, p5 d' C& I3 I& q4 {

  1. # C0 g( n' m* C5 i7 t" ^( @$ C! F
  2. import json
    8 b3 O/ R9 Q) j# A( J6 ]
  3. from web3 importWeb3, HTTPProvider. r2 Y+ X/ }8 w5 z
  4. from web3.contract importConciseContract
    2 I; V6 Y" o. I$ [' K! ^
  5. # compile your smart contract with truffle first
    / ]* g% v0 ~2 U) F, {# T
  6. truffleFile = json.load(open('./build/contracts/greeter.json'))
    6 s; Z, Q1 h8 J1 g( Y! i
  7. abi = truffleFile['abi']
    $ c" B; b) j( z: A/ }
  8. bytecode = truffleFile['bytecode']
    " }0 E! h# K, w/ G) ?( a, N& `6 F
  9. # web3.py instance
    ) s6 ?" n, f3 ~3 m" E8 \2 [" a
  10. w3 = Web3(HTTPProvider("https://ropsten.infura.io/<ApI Key here>"))
      t% [: j& w" A
  11. print(w3.isConnected())
    ; s# `8 m9 S+ T3 B
  12. contract_address = Web3.toChecksumAddress("<Deployed Contract Address here>")5 m% s- X# i9 t9 t8 p
  13. # Instantiate and deploy contract/ e; `) V. U) `7 a9 G
  14. contract = w3.eth.contract(abi=abi, bytecode=bytecode)' U6 s, S4 m3 G3 N8 C" ~  M
  15. # Contract instance
    - G  h. ^; r: t1 L/ Y2 D
  16. contract_instance = w3.eth.contract(abi=abi, address=contract_address)
    & H; [# ~1 y% R) [- M# K
  17. # Contract instance in concise mode
      C) D0 P$ z4 C' {
  18. #contract_instance = w3.eth.contract(abi=abi, address=contract_address, ContractFactoryClass=ConciseContract)
    6 q( c: F" `8 q% O
  19. # Getters + Setters for web3.eth.contract object ConciseContract0 K) c* G. G+ N/ X3 J% M" z
  20. #print(format(contract_instance.getGreeting()))
    / p4 B  n6 f6 x
  21. print('Contract value: {}'.format(contract_instance.functions.getGreeting().call()))
复制代码

, Y, g4 D- v$ |) A) K( S" {0 h( J$ ~
7 q* G& F$ U) |$ k; k
这是我所做的:
2 c9 E- T# ^2 k
# D9 }- h& `: g! N" a) E: {* O导入的 web3 库和所有其他必需的模块/ v: U4 A1 l" u$ Q9 \
通过指向 Ropsten Infura 节点启动 web3 提供程序
# R7 C" Q  v# @. ^1 d5 |通过指向 abi 和 contract_Address 创建合约实例(来自上一步)2 g* ~! Z2 [. Z; B
调用 getGreeting() 方法并在控制台打印结果$ f/ Q+ g8 n" f- M8 f4 l
结论6 h! T* |' [. e* N" {$ N

% P, h) v7 K+ W. n5 b* F8 b8 _您现在应该了解如何使用 web3.py 部署、交互和签署交易。让我们通过查看我使用 web3.py 创建的实时 DApp 并在此处使用 Flask 作为前端服务器来将所有部分组合在一起。它将帮助您更深入地了解使用 Python 进行 DApp 开发。- f; t& v- `% y% i
  t( p# U& F# C: c1 j1 R
, i$ z( R0 l8 D& n/ ~
参考 @温室小书生室dpython利用web3.py开发以太坊应用dapp的实战教程
$ P$ X7 v1 P; W7 Z' E1 u
标签: Python Python Python
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

常德小学生 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    13