用 Django 开发基于以太坊智能合约的 DApp



DApp概念和web3.py介绍

简单来说,DAPP和普通的App原理一样,除了他们是完全去中心化的,由类似以太坊网络本身自己的节点来运作的DAPP,不依赖于任何中心化的服务器,DAPP是去中心化的,可以完全自动地运行。

DAPP是Decentralized Application的缩写,中文叫分布式应用/去中心化应用,通常来说,不同的DAPP会采用不同的底层区块链开发平台和共识机制,或者自行发布代币(也可以使用基于相同区块链平台的通用代币)。

下面我们来介绍一下DApp开发,不可否认的是,对于DApp开发来说,主要挑战之一就是在于将智能合约与网站前端连接起来。最高效的方法是使用Web3库(Python或Javascript)来实现。这对于Javascript开发者来说可能很快完成,因为网上有许多Web3.js的教程,但对于Python开发者而言并不容易。

web3.py 是一个纯Python JSON-RPC 打包,用于与Ethereum以太坊节点进行通信。如需使用这个库,则需要一个运行中的Ethereum节点,并启用HTTP 或 IPC。虽然Web3.js社区非常庞大,但是Web3.py在Github上也拥有超过1.5k的星标,同时拥有133个贡献者以及一些具有吸引力的以太坊API。web3.py社区足够成熟,所以Python开发人员完全可以基于Web3.py来开发区块链DAPP。

开发所需工具

1、Remix IDE:一个开源IDE,不仅可以让你编写智能合约,而且还支持智能合约的测试,调试和部署。阅读官方文档以获取更多信息:https://remix-ide.readthedocs.io/en/latest/

2、Infura:一个托管的以太坊节点集群,可以将你开发的以太坊智能合约部署到infura提供的节点上,而无需搭建自己的以太坊节点。

3、Django 3.0:一个基于Python的开源网络框架,可以快速开发安全和可维护的网站。

python -m pip install Django

4、Web3.py:使我们能够与智能合约对话并调用其功能的工具。web3.py官方文档:https://web3py.readthedocs.io/en/stable/

pip3 install web3

接入区块链网络

首先,如下所示将 Remix 上的环境更改为Injected Web3,然后连接到Metamask上的Ropsten Network

在开发前,我们首先设置与区块链的安全可靠连接。如果没有Infura的话很难实现,现在我们只需要一个Infura API密钥。遵循以下步骤可以获取API Keyhttps://ethereumico.io/knowledge-base/infura-api-key-guide/

当获得API密钥并安装了上述工具,便可以进行下一步了。注意,为了确保项目的进行,您可能需要获取ROPSTEN Network的 Infura 密钥。

连接到WEB3.PY并开始交互

尽管此代码已经很清晰了,但这只是一个基本设置,我们还需要一些其它必要的因素,例如:

a、用于签署交易的私钥和公钥

b、为 web3创建一个HTTPProvider

c、存储智能合约的ABI和地址

d、通过传输ABIAddress作为参数来创建智能合约实例

现在我们通过智能合约有了一些安全的设置。但是,在掌握如何调用智能合约之前,首先要了解一下我们可以进行哪种类型的调用。

你想从智能合约中获取什么?

尽管我们可以执行多种功能,下面5项可能是最重要的:

a、从智能合约调用一个Getter函数:

虽然这似乎有些复杂,但是您可以按照下面提到的那样使用简单的方法来调用getter函数。

b、调用一个简单的Read_Only函数(简单方式):

智能合约中的read_only函数可以看作是仅在调用时返回特定数据的函数。例如,带有view关键字的此get_count函数仅在调用时返回post总数。

Solidity 代码写法如下:

function get_count() view public returns(uint){
return postCount;
}

为了方便调用,我们需要用一条简单的代码行来实现这些函数。以上就是我们需要做的。

c、用函数来实现Transaction(交易)

由于我们已经知道Read_Only函数,因此智能合约中可能还有其他函数会要求传递一些参数然后执行某些功能。用区块链技术术语来讲,调用这些函数被视为进行了一次交易,因为此类函数调用时会产生Gas价格。

让我们在智能合约中加入以下功能,Solidity 代码写法如下:

function createPost(string memory _content) public
{
require(bytes(_content).length > 0);
postCount++;
posts[postCount] = Post(postCount,_content,0,msg.sender);
emit PostCreated(postCount,_content,0,msg.sender);
}

此代码从用户那里获取content参数,然后将其添加到post列表中。当用户尝试更新区块链上的特定数据时,需要调用此类transaction进行一些操作。这样便形成一次交易。

那么如何进行交易呢?

这是一个复杂的过程,我们来分步解释。如第259行所示,我们没有调用函数createPost,而是建立了一个transaction。但是,buildTransaction函数接收了一个字典形式的数据作为参数。

``chainId:由于每个以太坊网络都有它的ID,简单来说就是代表我们连接的网络ID,在本例中3代表Ropsten`网络。

gas:我们已经知道执行每笔交易都需要gas,这个参数代表我们需要支付交易的最多的gas数量。

gasPrice: 表示以Wei为单位的'gas'单价

nonce: 表示用户前一次交易的计数

当我们根据自己项目的情况填写了参数后,就可以用signTransaction函数来对该交易进行签名了。该函数将此交易和私钥作为参数。

最后,当我们使用waitForTransactionReceipt函数收到交易回执时,便知道交易已完成。一旦获得此交易回执,就可以确保交易记录已成功添加到区块链中。

d、用以太币进行付款

如前所述,将以太币发送到一个智能合约或其他帐户也涉及类似以下的步骤,如建立交易,使用私钥签名以及获得确认交易回执。

但是,它涉及另外两个领域,例如:

to:表示交易的接收者

value:表示交易量

好了,这就是从一个帐户到另一个帐户进行转账交易所需要做的准备。

e、调用事件

首先我们需要明白什么是“事件”。在Solidity中,事件可以看作是交易日志中的实时记录,它不仅存储在区块链中,而且如果给定一个时间,可以借助智能合约来寻址。

尽管在文中代码没有使用任何事件,但在Web3.py的官方文档中我们可以了解调用事件的详细过程。

myContract = web3.eth.contract(address=contract_address, abi=contract_abi)
tx_hash = myContract.functions.myFunction().transact()
receipt = web3.eth.getTransactionReceipt(tx_hash)
myContract.events.myEvent().processReceipt(receipt)

以上这些就是在与智能合约进行交互时可能要使用的调用方法。

尽管我们已经很清楚地了解了使用web3.py与智能合约进行交互并调用特定函数的过程,但仍有最后一件事需要理解,即智能合约返回数据后我们需要做什么?

由于我们使用的是Django网络框架,因此非常需要了解它是如何处理智能合约的响应并根据需要使用它。

在Django中处理智能合约的反馈

智能合约有两种可能的反馈方式:

第一种情况,我们可能进行了一笔交易(向区块链中添加了一些东西或进行了付款)。在这种情况下,只需简单地获取交易回执。因为我们只需要确认交易确实已执行即可,其它都不需要做。

第二种情况,我们可能需要调用一个返回数据列表的函数。嗯,这就是我们真正感兴趣的。让我们分析一些代码来了解第二种情况。

posts_data传递到模板的函数

在这里,我们实际上所做的只是调用get_posts_from_contract()函数。从智能合约调用post数组的功能。

我们的智能合约包含一系列数据,这些数据包含来自用户的所有post,其打赏额以及作者的地址。在此函数中,我们只需调用该数组并返回它。

因此,当posts()函数调用get_post_from_smart_contract()函数时,它基本上会获取嵌套的数据列表。

现在出现的最关键的问题是,我们如何处理模板中的这个列表?

Django中的模板部分

由于智能合约中的数据是嵌套列表,因此在Django模板中处理数据列表的有效方法如下:

{% for data in data_from_views.py %}

...
<h1>{{ data.0 }}</h2>
<h1>{{ data.1 }}</h2>...

{% endfor %}

这正是我们在模板中处理它的方式。代码如下所示:

总结

我们不仅学习了用Python进行智能合约交互的整个过程,而且还以我们想要的方式来处理其响应。


如果将其部署到服务器上运行,上面的模板就会呈现出来,你将拥有一个完整的DApp网站,不仅可以与区块链进行交互,还可以在其上进行交易和读写。