/ 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 库与区块链进行交互。
) i& I8 A( `, W' A% c# x, Z
Dapps 开发包括三个简单的步骤:7 V. @( w0 F2 q+ m( T$ h
- 在区块链网络上部署智能合约
- 从部署的智能合约中读取数据
- 将交易发送到部署的智能合约
* s; f; h0 i" f
安装
Python 2.7 +
Node.js0 J; x" r+ Q& s$ ^' K
Truffle
npm install -g truffle0 O# J( J0 x5 q' |
Pip
npm 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
前往 Infura 网站并注册。创建一个新项目并复制 Ropsten Infura RPC URL。我们将把我们的智能合约部署到 Ropsten 测试网络。/ J/ y, [; w9 V
智能合约
每个程序员都用他们最喜欢的编程语言执行了一个“hello world”程序,以了解运行该语言的基础知识。这是我们使用 Solidity 语言编写的简单的“hello world”版本的智能合约,我们可以在区块链上添加问候语并检索它。Solidity 是编写智能合约最常用的语言,它编译为可以在节点上运行的以太坊虚拟机上执行的字节码。
) E% F# E0 R1 x& m
- pragma solidity ^0.5.7;
- contract greeter{
- string greeting;
- function greet(string memory _greeting)public{
- greeting=_greeting;
- }
- function getGreeting() public view returns(string memory) {
- return greeting;
- }
- }7 Q; F9 G, X+ ` l( E. c
- q6 g) I- ~3 N- K- _& ^7 }
您可以通过传递字符串值使用 greet() 方法添加问候语,并使用 getGreting() 方法检索问候语。
$ 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) 创建项目:
; I+ h! I, j: O
mkdir pythonDapp& f4 o) R- I- I
cd pythonDapp
truffle init
成功初始化项目后,转到您的文件夹并在 /contracts目录中创建 greeter.sol 文件。在网络上部署合约之前,我们必须编译它并构建工件。
/ c& T/ {0 H0 w3 |9 b- W& r
b) 智能合约的编译:因此,对于编译,我们将使用 Truffle solc 编译器。在您的主目录中,运行以下命令:! k9 m" q% a& S$ [; D( @; ?
truffle compile
(or)
truffle.cmd compile #(for windows only)1 L- C; R- E$ n x- I9 S! P- Z
. o2 [. ^' Q4 i" x6 ~
上面的命令将在 /contracts 目录中编译你的合约,并在 /build 目录中创建二进制工件文件 greeter.json。
& N3 U# T6 s! [; ?
c) 部署合约:打开您的 Python IDLE 编辑器,并在主目录 deploy.py 中使用以下代码创建一个新文件,然后在您的目录中运行 py deploy.py。
# h# e2 z' N0 K' H
- import json
- from web3 importWeb3, HTTPProvider9 y) d' u; j$ J
- from web3.contract importConciseContract/ R3 p$ A9 S0 }* W1 m {6 M ?/ t
- # web3.py instance
- w3 = Web3(HTTPProvider("https://ropsten.infura.io/v3/<API key>"))0 Y* r8 F0 j% Y' g9 v# q) W2 g
- print(w3.isConnected())
- key="<Private Key here with 0x prefix>"
- acct = w3.eth.account.privateKeyToAccount(key)9 r2 j& y( d2 I; b
- # compile your smart contract with truffle first! ~3 ]' d( q! J# y6 _! @
- truffleFile = json.load(open('./build/contracts/greeter.json')), m) c7 |: k( y, v q& b( `- @* d
- abi = truffleFile['abi']2 V8 `4 \' t6 A
- bytecode = truffleFile['bytecode']
- contract= w3.eth.contract(bytecode=bytecode, abi=abi)' n) b d. H* ]) m& @
- #building transaction9 j. \4 M2 h* e/ k7 Z
- construct_txn = contract.constructor().buildTransaction({
- 'from': acct.address,
- 'nonce': w3.eth.getTransactionCount(acct.address),, O1 ^5 e! t6 E w% ^
- 'gas': 1728712,
- 'gasPrice': w3.toWei('21', 'gwei')})- Q% g, @, N& z b
- signed = acct.signTransaction(construct_txn)& F4 |) _% T5 K E# }+ c' L& \. J
- tx_hash=w3.eth.sendRawTransaction(signed.rawTransaction)3 _* \" b0 G% g2 u4 W7 @5 n
- print(tx_hash.hex())
- tx_receipt = w3.eth.waitForTransactionReceipt(tx_hash)
- print("Contract Deployed At:", tx_receipt['contractAddress'])
1 B9 G: q- n. ]; ?& q
这是我所做的:: @" G6 S7 p: p# k: G$ \% A3 K7 K
& V p: R+ D7 I0 R# g
导入的 web3 库和所有其他必需的模块
通过指向 Ropsten Infura 节点启动 web3 提供程序
添加了用于签署交易的帐户地址和私钥。不要忘记在代码中添加您的凭据。
通过指向 Truffle 编译的工件文件greeter.json的abi和字节码启动合约实例
添加了带有随机数、gas、gasPrice 等参数的construct_txn。此处,gas 是指交易应在以太坊中使用和支付的最大计算资源量。gasPrice 是指在交易中使用该数量的 gas 时的最小 Ether 数量。to 指的是您发送交易的地址。仅当您将 Ether 发送到帐户或智能合约时才需要 to 参数。; d" `) S* N1 X
使用我们的私钥签署交易并在网络上广播。
在控制台中记录交易哈希和部署的合约地址。根据以太坊的说法,事务处理时间 <20 秒。所以你必须等待 20 秒才能获得部署的合约地址。您的后端现在已成功部署在以太坊区块链上。现在您可以使用此地址与您的智能合约进行交互。复制此合约地址。: l/ Y. T0 \9 a$ x! i; o* f; b( X' _
2. 向部署的合约发送交易
在我们的合约中,有一个方法greet()。我们可以单独使用这种方法在我们的合同中添加问候语。让我们看看我们如何使用 web3.py 来做到这一点。打开您的 Python IDLE 编辑器并使用以下代码创建一个新文件 sign.py。然后在您的目录中运行 py sign.py。0 P% M, D/ y# p/ g
- import json3 [" Y. D3 r& b/ {. b
- from web3 importWeb3, HTTPProvider
- from web3.contract importConciseContract
- # compile your smart contract with truffle first' t v) `" Y, H- P- A. F
- truffleFile = json.load(open('./build/contracts/greeter.json'))+ _ c3 f5 f; M2 ]" v. g0 R
- abi = truffleFile['abi']
- bytecode = truffleFile['bytecode']3 q9 F4 R+ S6 v4 z' U5 K
- # web3.py instance
- w3 = Web3(HTTPProvider("https://ropsten.infura.io/v3/<API key>")) #modify+ \! |7 c& y, J9 f' X/ b
- print(w3.isConnected())
- contract_address = Web3.toChecksumAddress("<Deployed Contract Address here>") #modify E3 D5 [! j( b+ x1 L9 j6 b
- key="<Private key with 0x prefix here>"#modify1 J7 D8 l, f# m7 w5 [
- acct = w3.eth.account.privateKeyToAccount(key); R2 J( {9 i/ L J
- account_address= acct.address' h+ v$ o7 n# m. y; A& f' Z
- # Instantiate and deploy contract
- contract = w3.eth.contract(abi=abi, bytecode=bytecode)
- # Contract instance
- contract_instance = w3.eth.contract(abi=abi, address=contract_address)
- # Contract instance in concise mode
- #contract_instance = w3.eth.contract(abi=abi, address=contract_address, ContractFactoryClass=ConciseContract)# E- v4 J8 z1 @" [. W- s. q
- tx = contract_instance.functions.greet("Hello all my goody people").buildTransaction({'nonce': w3.eth.getTransactionCount(account_address)})
- #Get tx receipt to get contract address
- signed_tx = w3.eth.account.signTransaction(tx, key)- F& v9 n0 H/ o1 }
- #tx_receipt = w3.eth.getTransactionReceipt(tx_hash)& A9 Z' h9 v/ Z6 n! e9 b. V/ Z
- hash= w3.eth.sendRawTransaction(signed_tx.rawTransaction)
- print(hash.hex())
W" n, D" B! U9 I+ E& C! v
这是我所做的:6 w5 Q% V) q9 Q/ f7 }2 T
( P. D" T) y) c
导入的 web3 库和所有其他必需的模块
通过指向 Ropsten Infura 节点启动 web3 提供程序
添加了用于签署交易的帐户地址和私钥+ u9 ?: ~$ `1 x; N2 u2 _
通过指向 Truffle 编译的工件文件greeter.json的abi和字节码启动合约实例
创建 tx 对象以添加问候语“hello all my goody people”并建立交易8 |2 P) Y8 h1 j
使用我们的私钥签署交易并在网络上广播。
在控制台中记录交易哈希。您可以使用您的交易哈希在 etherscan 上检查交易状态。一旦交易被矿工验证,我们的问候语将被添加到区块链上。您可以使用 getGreeting() 函数检索问候语,如下所述。
3. 从部署的智能合约中读取数据
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
- - u/ K1 _! q( `0 {' W- i5 \
- import json
- from web3 importWeb3, HTTPProvider
- from web3.contract importConciseContract
- # compile your smart contract with truffle first
- truffleFile = json.load(open('./build/contracts/greeter.json')); {0 L( E4 V- i# q
- abi = truffleFile['abi']2 [+ Y: E4 H* U% P* y9 C) B. x h
- bytecode = truffleFile['bytecode']
- # web3.py instance
- w3 = Web3(HTTPProvider("https://ropsten.infura.io/<ApI Key here>"))
- print(w3.isConnected())3 g }. c: J: w! N& m! {1 P
- contract_address = Web3.toChecksumAddress("<Deployed Contract Address here>")
- # Instantiate and deploy contract
- contract = w3.eth.contract(abi=abi, bytecode=bytecode)
- # Contract instance1 V+ h( M; P& r# \% H
- contract_instance = w3.eth.contract(abi=abi, address=contract_address)% A8 w9 P; u8 l# d" c+ j
- # Contract instance in concise mode
- #contract_instance = w3.eth.contract(abi=abi, address=contract_address, ContractFactoryClass=ConciseContract)
- # Getters + Setters for web3.eth.contract object ConciseContract* u( R8 C7 f5 F; _2 `; U
- #print(format(contract_instance.getGreeting()))
- print('Contract value: {}'.format(contract_instance.functions.getGreeting().call()))
( R$ M; X. E$ |, D! W$ {$ @) e4 D
这是我所做的:: w# B. c9 F! J
* D! `2 p3 u% r* ?, b( [
导入的 web3 库和所有其他必需的模块
通过指向 Ropsten Infura 节点启动 web3 提供程序% O$ k! @! P' ~6 G' }' f, N1 m
通过指向 abi 和 contract_Address 创建合约实例(来自上一步)
调用 getGreeting() 方法并在控制台打印结果
结论3 N6 n8 c1 U! q" Z6 t: y
5 {9 ^, F$ Y/ }/ p
您现在应该了解如何使用 web3.py 部署、交互和签署交易。让我们通过查看我使用 web3.py 创建的实时 DApp 并在此处使用 Flask 作为前端服务器来将所有部分组合在一起。它将帮助您更深入地了解使用 Python 进行 DApp 开发。
6 s) L, G$ m2 D8 V" t
h) n8 j: O- m1 N$ }
参考 @温室小书生室d 《python利用web3.py开发以太坊应用dapp的实战教程》; Z5 _' T+ ^ y5 v9 X