banner
leaf

leaf

It is better to manage the army than to manage the people. And the enemy.

区块链综合应用开发实践

在区块链的开发过程中,除了开发自己的区块链以及基于某个公链或框架进行开发外,还有一些第三方平台提供了工具可以快速生成数字加密资产并进行交易,如国外的 Opensea(网址 http://opensea.io)和 RareBits(网址 https://rarebits.io/),国内的 BIGE(网址 http://bige.game/)等。

3 个开发实例,包括一个以太坊查询分析系统开发实例、一个 ERC20 代币的开发实例和一个基于 OpenSea 平台的数字加密资产开发实例。

●了解以太坊测试网络 Ropsten。

●掌握 web3.py 库的功能。

●掌握以太坊数据的基本查询和分析方法。

●了解 ERC20 代币的开发。

●学习加密资产的开发过程。

●了解 OpenSea 交易平台。

以太坊之 DApp 开发实战中搭建了一个以太坊的本地测试环境,但本地测试环境的数据比较少,无法体现真实的以太坊网络的数据情况。所以在选择以太坊的公开测试网络 Ropsten 作为测试环境。

Ropsten 是 2016 年 11 月上线的一个以太坊测试网络,以斯德哥尔摩(瑞典首都)的一个地铁站命名。Ropsten 采用工作量证明的共识机制,它是对以太坊现有生产环境的最好模拟,在以太坊主网的系统和网络状态等方面都比较近似。而且 Ropsten 测试网络上的以太币是免费的,通过对接 Ropsten 测试网络来对以太坊进行各种测试和开发成本极低,所以选择 Ropsten 测试网络性价比很理想。下面使用之前第 5 章介绍的 MetaMask 插件连接到 Ropsten 测试网络。

(1)连接 Ropsten 测试网络

单击 MetaMask 插件,打开选项界面,再单击网络选项更改连接网络为 Ropsten 测试网络,如图 8-1 所示。

(2)创建测试账户

切换网络成功后接着单击用户头像,选择创建用户在 Ropsten 测试网络中生成一个新的账户,

在弹出界面中输入用户名并单击 “CREATE” 按钮进行创建,如图 8-3 所示。

(3)查看账户余额

创建完成后进入账户详情页面,新的账户余额为 0 个以太币,如图 8-4 所示。

(4)获取以太币

为了进行对接测试,最好能在 Rospten 测试网络中获取一定数量的以太币(对以太坊网络进行更新操作需要消耗以太币)。在 Rospten 测试网络中获取以太币的方法主要有以下几种。

●在 http://faucet.ropsten.be:3001 / 上申请,需要输入在 Ropsten 网络上的账户地址就可以了,转币操作非常迅速,目前一次可申请 3ETH。

●找朋友给自己转币。

●自己挖矿。

毫无疑问,第一种方式是最方便快捷的,下面进行申请操作

2. 申请以太币

申请以太币需要输入账户地址。

(1)复制账户地址

单击账户左上角菜单可以看到账户详情,在地址右边有一个复制按钮,单击复制地址信息.

(2)在 Ropsten 上进行申请

得到账户地址后,在浏览器中访问 http://faucet.ropsten.be:3001/,打开的页面上输入刚才复制的账户地址,如图

image

(3)申请成功

单击 “Send me test Ether” 按钮申请测试以太币即可。申请成功后,页面下部会出现申请成功信息和转账交易记录的哈希值,如图

image

注意,申请到的以太币需要 Ropsten 网络中其他结点确认,故申请成功后一般还需要半天左右时间才能在 MetaMask 看到申请到的以太币信息。

已经使用 MetaMask 插件创建了 Ropsten 测试网络的测试账号,为了对接这个测试网络的接口进行数据的查询和获取,在这里将使用 web3.py 库与 Ropsten 测试网络进行对接。

1.web3.py 介绍

web3.py 是以太坊接口的 Python 封装,通过 JSON-RPC 连接以太坊网络进行交互。web3.py 和 web3.js 类似,其中 web3.js 主要适合浏览器端的 Dapp 的开发,而 web3.py 是基于 Python 开发的,更适合在服务器使用。

2.web3.py 的安装使用

web3.py 可以使用 Python 的包管理工具 pip 进行安装,首先新建一个虚拟环境。

(1)新建虚拟环境

这里先新建一个名为 ch8 的 Python 虚拟环境(web3.py 支持 Python3.5 以上版本),命令如下:

virtualenv venv-p python3

(2)安装 web3.py

创建完成后激活这个虚拟环境,然后使用 pip install web3 命令安装 web3.py,该命令会自动下载安装依赖库并打印安装信息,如图

web3.py 提供了数据过滤接口、服务提供商、以太坊命名服务、网络信息、账户信息、区块信息等几个主要的功能接口,详情可以访问 web3.py 的官网 https://web3py.readthedocs.io/en/stable/index.html 进行查询。

(3)申请测试结点

安装了 web3.py 后需要申请一个用于连接 Ropsten 测试网络的测试结点。这里使用 Infura,Infura 是一个以太坊结点服务提供商,它提供公开的 Ethereum 主网和测试网络结点,开发者可以到 Infura 官网进行申请。在浏览器中打开 https://infura.io/ 看到 Infura 的页面,如图

image

单击页面上的 “GET STARTED FOR FREE” 按钮开始免费申请。免费申请需要填写姓名、邮箱和密码等基本信息信息填写完毕后,单击 “SIGN UP” 按钮进行注册。注册后提示已发送一份确认邮件到已填写的邮箱中,如未收到可以单击 “RE-SEND VERIFICATION EMAIL” 按钮重新发送确认邮件,所示。

单击邮件中的确认连接后会自动登录进入注册账户中。顺利登录后会提示用户新增一个项目,项目名任意,这里项目名为 “自学区块链”,单击 “CREATE PROJECT” 按钮创建项目,如图

图 8-12 创建项目

创建完成后进入项目详情页面。详情页面中显示了用来连接以太坊网络的 API KEY、API SECRET 和可连接的结点地址 ENDPOINT,以及这个结点上智能合约的白名单列表。这里选择 Ropsten 测试网络的结点,如图 8-13 所示。

3. 使用 web3.py 连接网络

在上面得到 Ropsten 测试网络的连接结点后可以使用 web3.py 进行连接。先从 web3.py 导入 Web3 和 HTTPProvider,然后连接项目中的 Ropsten 测试结点,连接后使用 isConnected 方法检查连接状态,返回 True 说明连接成功,如图 8-14 所示。

连接成功后就可以使用 web3.py 提供的 getTransartion 等方法查询 Ropsten 网络数据了。

  项目目录

(3)创建应用

初始化项目之后,可以开始实现功能代码。先新建一个 Flask 应用并初始化 Web3 进行连接,在 app.py 中编

image

完成后执行 python app.py 命令就可以启动这个应用。启动的应用默认在 5000 端口进行监听,处理请求并返回结果。

(4)实现基础模板

创建应用后开始编写页面。在 Flask 中默认使用的是 Jinja2 模板语言来实现模板功能(Jinja2 有个强大的功能即模板继承功能。模板继承允许开发者创建一个基础的骨架模板,这个模板包含网站的通用元素,在子模板中可以通过继承这个基础模板拥有这些通用元素,不同的页面元素可以通过重载来实现,就像 Python 类的继承和重载一样简单),因此可以先编写一个基础模板,将页面公共的部分都放到这个基础模板中,其他页面继承这个模板就会拥有这些公共的部分,再加上页面需要的定制内容并用 bootstrap 来美化页面样式就可以快速实现一个页面。这样做的好处是可以避免编写重复的内容,提高开发效率,具体操作为:在当前目录的 templates 文件夹新建一个 layout.html 的文件,在这个文件中引入 bootstrap 相关的 css 和 js,代码

image

image

其中类似 “{% block ×××%}{% endblock %}” 的内容是供子模板中重载的区域,子模板可以通过重载添加自定义的内容。下面开始实现第 1 个功能,第 1 个功能是查询并显示 Ropsten 测试网络中的最新区块

查询 Ropsten 测试网络中的最新区块信息,可以通过 web3.py 的函数 getBlock 来实现,这个函数返回的格式是一个 Json 字符串,前端 HTML 页面负责将这个 Json 字符串显示出来。在 app.py 中实现一个名为 get_last_block 的函数,在函数中调用 getBlock(“latest”)函数,然后从返回的区块信息中提取主要内容传递给模板进行显示,代码如下

image

image

以上代码从获取到的区块信息中提取主要区块信息,并将这些信息封装到一个字典中传递给模板 block.html。block.html 模板先是继承 layout.html 模板,然后使用 jquery.json-browse 的 jquery 插件进行显示。jquery.json-browse 的作用是美化 Json 数据的显示,并且可以对 Json 数据进行展开和折叠处理,block.html 代码如下

image

以上查询最新区块的代码编写完成后启动应用可查看效果,打开浏览器访问 http://127.0.0.1:5000,就可以看到最新区块的信息,如图 8-16 所示,显示了最新区块的信息,包括矿工地址(miner)、哈希值(hash)等。

2. 查询区块的交易数据

在一个区块中往往存储了很多个交易记录。在图 8-16 中的区块信息中有一个 transactions 字段,其中包含了一系列哈希值,每一个哈希值对应的就是一个交易记录。在这一节中实现的功能是使用 web3.py 中的 getTransaction 函数查询哈希值对应的交易信息并将交易信息显示在 HTML 中。在 app.py 中实现一个 handle_transaction 函数,该函数接收 GET 和 POST 两种请求方式。GET 请求返回一个包含输入框和按钮的 HTML 页面,POST 会传递一个交易信息的哈希值,函数内调用 web3.py 的 getTransaction 函数查询对应的交易并将结果返回,代码如下

image

image

image

更新 app.py 后,再新建一个 transaction.html 模板文件,该模板文件依旧从 layout.html 继承而来。模板中显示一个输入框和按钮,在输入框输入交易哈希值后,单击 “搜索交易” 按钮会将交易哈希值的请求数据发送到应用,从应用得到交易数据后再使用 jquery.json-browse 命令显示 Json 数据,代码如下

image

image

完成后重启应用,查看页面效果,可以看到一个用来搜索交易的页面。在浏览器中输入 http://127.0.0.1:5000/transaction,打开该页面,然后在输入框输入一个交易 id,单击 “搜索交易” 按钮即可看到交易详情,如图所示

image

完成了区块和交易数据的查询功能,再来实现查询账户余额的功能。查询账户余额的实现逻辑和查询交易数据类似。在 app.py 中实现一个 get_balance 的函数,接收 GET 和 POST 两种请求方式。GET 请求返回一个包含输入框和按钮的 HTML 页面,POST 请求接收账户地址信息并通过 web3.py 的 getBalance 函数获取账户余额,代码可以根据 “2. 查询区块的交易数据” 部分稍作修改即可。完成后在浏览器中打开 http://127.0.0.1:5000/balance,输入账户地址即可查询对应账户的余额,如图

image

区块信息分析#

简单分析一下 Ropsten 测试网络中的区块信息。先写一个 Python 脚本下载 Ropsten 测试网络中的前 10000 个区块,并通过 pickle 模块将这些数据保存下来。pickle 是 Python 用来将 Python 对象保存为文件的一个模块,使用 pickle 可以方便地存储和读取 Python 对象。

(1)下载区块数据

新建一个 eth_helper.py 文件,在这个文件中新建一个 download_blocks 函数用来循环下载区块数据,下载完成后,使用 pickle 将这些区块数据保存到一个名为 block.pkl 的文件中,代码如下

image

运行 python eth_helper.py 命令执行脚本。脚本下载区块数据需要一段时间,下载完成后会在本地自动生成一个 block.pkl 的文件,里面包含了 10000 个区块数据,如图

image

2)加载区块数据

在 app.py 中新建一个名为 visualization 函数,用来加载已经下载好的区块数据并将其中的区块难度提取出来,放到一个列表中传递给 HTML 页面(visualization.html)以供展示,代码如下

image

这里只是将区块难度提取出来做分析处理,有兴趣的读者也可以提取其他字段进行分析。为了方便通过 HTML 页面进行展示,这里将区块序号和区块难度分别放到一个独立的列表中。

(3)对数据进行可视化

最后一步是对数据进行可视化展示。这里使用 ECharts 进行可视化操作。ECharts 是一款由百度前端技术部开发的、基于 JavaScript 的数据可视化图表库,可以提供直观、生动、可交互、可个性化定制的数据可视化图表。使用 ECharts 对数据进行可视化的方法也很简单,只需要在 HTML 页面中包含 ECharts 的 js 库文件,然后新建一个一定大小的 div 元素,再编写一段 js 代码加载数据,即可进行数据可视化显示。

新建一个 visualization.html 文件,这里选择折线图的形式进行区块难度数据的可视化。编写代码如下

image

image

image

代码编写完成后重启 Flask 应用,访问 http://127.0.0.1:5000/visualization 就可以看到可视化效果,如图

image

从图中可以看到,在 Ropsten 测试网络中区块难度的值是直线上升的,这表明随着区块链的不断延长,生成区块的难度越来越大。

以上就是一个简单的以太坊查询分析系统,有兴趣的读者还可以进一步分析以太坊的其他数据,如区块的生成速度、区块每日生成的个数以及待确认的区块数目等。若要分析实际环境中的以太坊,只需要把上面的 Ropsten 测试结点地址(http://ropsten.infura:io/v3/×××)换成正式结点地址就可以了。

ERC20 可以简单理解成以太坊上的一个代币协议,所有基于以太坊开发的代币合约都遵守这个协议。遵守这个协议的代币叫作 ERC20 代币。本案例将开发一个名为 Mini Token 的 ERC20 代币。

密数字货币的种类纷繁复杂,比特币、瑞波币、小蚁币等众多老牌币种,都有独自的链,在自己的链上运行着自己的加密数字货币。除了这些之外,还有一种平台型代币,它们是依托以太坊而创建的,没有自己的链,而是运行在以太坊之上。当前市面上十有八九的数字货币都属于平台型代币。这些代币都遵守 ERC20 代币协议,都是标准化的代币,这些标准化的代币可以被各种以太坊钱包支持。被以太坊钱包支持的代币可用于各种项目的开发,也可以提交到各个交易所进行交易。

之所以叫 ERC20 代币,是因为 ERC20 是在 2015 年 11 月以太坊社区提出的代号为 20 的一项标准,符合这个标准的都是 ERC20 代币。在 ERC20 标准出现之前,代币的标准不统一,发行代币是一件非常麻烦的事,对开发者来说既需要单独开发智能合约,还并不能做到多种钱包的兼容。在 ERC20 标准出现后,发行基于 ERC20 标准的代币变得很简单,开发一个 ERC20 代币基本不超过 10 分钟,50 行代码就能实现。

ERC20 是各个代币的标准接口,开发者需要将这些标准接口集成到他们的智能合约中,以便能够执行以下操作:

●获得代币总供应量。

●获得账户余额。

●转让代币。

●批准花费代币。

ERC20 让以太坊区块链上的其他智能合约和去中心化应用之间实现了无缝交互。ERC20 标准的接口文件如下

image

其中的含义如下。

●name 是需要指定名字,比如可以叫作 MyToken。

●symbol 是代币的符号,类似于常见的 BTC、ETH 等。

●decimal 是代币最少交易的单位,它表示小数点的位数,如果设置为 1,那么最少可以交易 0.1 个代币。

●totalSupply 是指总发行量。

●balanceOf 返回某个地址(账户)的账户余额

●transfer 实现转账一定数量(_value)的代币到目标地址(_to),它会提供一个返回值来说明是否转账成功,并且会触发 Transfer 事件。

●transferFrom 从一个地址(_from)转账一定数量(_value)的代币到目标地址(_to),也会提供一个返回值来说明是否转账成功,同样也会触发 Transfer 事件。

●approve 授权第三方(_spender)从发送者账户转移一定量(最多为_value 数量)的代币。第三方通常是某个智能合约,可以通过 transferFrom()函数来执行具体的转移操作。

●allowance 返回_spender 仍然被允许从_owner 提取的金额。

●Transfer 和 Approval 事件是为了记录日志用的。前者是在代币被转移时触发,后者是在调用 approve 方法时触发。

ERC20 代币不是一个 DApp,它是智能合约的重要应用之一,ERC20 代币也使用 Solidity 语言进行开发,开发环境一般选择 Remix(Remix 是一个在线的、用来开发以太坊智能合约的 IDE,地址是 http://remix.ethereum.org)。

这里要实现一个名为 “Mini Token” 的代币,符号为 “MT”,总发行量为 1000 枚。实现的方法是修改 ERC20 标准接口中相应函数的内容,如将 name 改为 “Mini Token”,symbol 改为 “MT” 等,完整代码如下

image

image

image

image

image

将上述代码复制粘贴到 Remix 的编辑器中,执行编译,并部署到本地测试环境中,这样 Mini Token 就发布成功了。从合约的详情中可以看到 Mini Token 的名称、符号和总发行量等信息,如图

image

单击合约右侧的复制按钮,将 Mini Token 的地址复制到剪切板。然后打开 MetaMask 的账户选项,选择 “ADD TOKEN”,如图 8-22 所示。

在 Add Tokens 对话框中选择 “Custom Token”,在 “Token Address” 文本框中填入刚才复制的 Mini Token 的地址,之后下面的符号栏和精度栏会自动补充,然后单击 “Next” 按钮继续,如图

最后,再单击 “ADD TOKENS” 按钮,将 Mini Token 添加到账号中,如图 8-24 所示。

完成以后,在账户界面就可以看到新创建的代币,并可以将这些代币进行交易或转账

2017 年底,以太坊上发布了一款火爆的小游戏加密猫(CryptoKitties),它是加密猫的养成与繁殖游戏,利用以太币作为该游戏的唯一交易货币,两只加密猫交配而生出的子孙会从他们父母基因组中通过遗传算法获取新的基因,这些基因决定了外观、个性与特征等。每只猫都是独一无二的,100% 归所有者拥有;加密猫不能被复制、带走或毁坏,但可以购买或出售它。加密猫可以作为一个收藏品并在区块链中被安全地记录。加密猫的作者 Axion Zen 后来还定义了一种代币标准 ERC721,开发者可以基于这个标准发布数字资产。在 ERC20 中所有符合 ERC20 的代币都是相同的,任何两个 ERC20 代币之间没有区别;而在 ERC721 中每种数字资产都有它唯一的标识,没有两种符合 ERC721 标准的数字资产是完全相同的,这与 ERC20 有着明显的不同。

ERC721 官方简要解释是 “Non-Fungible Tokens”,翻译为不可互换的代币,英文简写为 “NFT”,简单理解为每个代币都是独一无二的。以加密猫来解释的话,每一只加密猫都是独立的代币,而且每只加密猫都有它独一无二的特征,无法相互替换。而 ERC721 就是定义了这样一个标准来实现这一类的加密资产。

本节的实例就是实现一个类似于加密猫的数字资产 —— 加密猪。要开发这类数字资产,需要实现符合 ERC721 标准的智能合约,然后基于这个智能合约实现一套用户界面来展示开发的数字资产。

随着类似加密猫之类数字资产的增多,有人就开始创建一个专门用来进行此类加密资产交易的平台,其中 OpenSea 是世界上最大的加密资产交易平台。开发者不再需要自己从头开发,只需要在 OpenSea 平台上按照流程进行操作就可以快速开发出一个 ERC721 数字资产。本节接下来首先介绍 OpenSea,然后讲解如何在 OpenSea 上开发和交易数字资产。通过本案例可以学到如何开发一个符合 ERC721 标准的数字资产,以及如何对这类资产进行交易。

penSea 是一个基于区块链的加密资产交易平台,为广大用户提供加密资产的购买和销售等服务,OpenSea 首页如图

OpenSea 提供了一份开发文档,让开发者在几分钟内就可以开发完成属于自己的店铺,可以访问 https://docs.opensea.io/docs 进行查阅,OpenSea 提供的示例是交易各种海洋生物加密资产,所示。

这里参照这个海洋生物加密资产的开发过程来开发自己的一个加密资产 —— 加密猪。加密猪遵循以太坊 ERC721 标准,并加入权限控制的功能。开发步骤依次为创建和实现加密猪的智能合约、加密猪的展示页面和用户界面,以及加密猪交易功能。

本实例基于 Truffle 框架进行开发,开发过程中需要使用 NodeJS 包管理器 npm 安装依赖库,开发之前应确保系统中的 npm 工具可用,然后选择一个常用的文本编辑器(如 VScode、Sublime)等就可以开发这个加密猪了。

这里智能合约的开发基于 OpenZeppelin 库。OpenZeppelin 是用 Soildity 语言实现的一个开源库,里面包含了已知智能合约的最佳实践。OpenZeppelin 提供了开发智能合约所需的各种重要功能,使我们可以基于它在更少的时间内创建更安全的智能合约。下面开始正式开发智能合约。

(1)初始化智能合约

这里先在本地任一目录下新建一个 LittlePig 的文件夹,创建完成后进入文件并使用 truffle init 命令初始化一个 Truffle 项目,如图

image

初始化项目

初始化后再安装 OpenZeppelin 库,安装命令如下:

npm install openzeppelin-solidity

安装完成后开始实现智能合约的功能。

(2)实现 LittlePig 智能合约

LittlePig 智能合约的功能实现比较简单,只需要基于 openzeppelin-solidity 库进行二次开发。在当前目录的 contracts 文件夹下新建一个 LittlePig.sol 的文件。在文件中编写一个 LittlePig 的类,这个类继承于 ERC721Token 和 Ownable 这两个基础类。其中 ERC721Token 是 ERC721 标准的基础类,Ownable 提供了权限控制的功能。继承后在类的主体部分还需要实现 tokenURI、baseTokenURI、isApprovedForll 等函数。值得注意的是有两点,一是 tokenURI 函数,这个函数返回一个 URI 地址,这里是 https://little-pig-api.herokuapp.com/api/pig/,请求这个 URI 会返回每个 ERC721 资产的属性,如名称、描述和图片等,这些属性将被展示在 OpenSea 平台上;二是 isApprovedForAll 函数,它用来控制获取 OpenSea 数据的白名单列表,具体代码如下

image

实现智能合约代码后就可以开始发布智能合约了。

(3)发布智能合约

这里使用之前注册的 Infura 账户(参数 8.1.2 节对接以太坊接口中申请测试结点部分)发布到 Ropsten 测试网络上。发布的方法也比较简单,使用 HDWalletProvider 连接到 Ropsten 测试网络并进行发布操作。其中连接过程中需要配置钱包的助记词(用来推算钱包信息的十几个英文单词,讲过)和 Infura 的接口地址,在 truffle.js 文件中配置如下

image

image

配置完成后,使用 truffle deploy--network ropsten 命令将智能合约部署到 Ropsten 测试网络中,部署成功后可以看到交易哈希值(transaction hash)和合约地址(contract address)等信息

image

4)生成加密资产

成功发布智能合约后,就可以调用智能合约生成属于自己的加密资产。生成的方法是使用 HDWalletProvider 连接到 Ropsten 测试网络,然后加载智能合约并调用 mintTo 函数生成加密数字资产。这里新建一个 mint.js 文件,在文件中编写代码如下

image

image

完成 mint.js 后通过在终端中执行 node mint.js 就可以生成加密资产,上述代码中设置生成 12 个加密猪。可以在终端上看到生成的 12 个哈希值,也就是 12 个加密猪如图

image

生成加密猪的哈希值

以上生成的这样的加密猪就是属于自己的加密资产,可以进行交易和转让。为了让这些加密猪看起来更加直观和吸引人,可以给每个加密猪添加一些属性数据,这样在 Opensea 上每个加密猪都会展示出不同的形象。

前面的智能合约中实现了一个 tokenURI()方法,这个方法针对每个 Token 返回一个唯一的 URI,请求这个 URI 就可以返回这个 Token 对应的属性数据。比如,对于 Id 为 1 的 Token 返回的 URI 是 https://little-pig-api.herokuapp.com/api/creature/1。请求这个 URI 会返回如下的 Json 数据:

image

其中 description 字段是加密猪的描述,external_url 字段是加密猪的外部链接,image 是加密猪的图片地址,name 是加密猪的名称,attributes 是加密猪的自定义属性列表。

添加好属性数据后,即可在 Opensea 平台上查看该加密资产的信息。查看的链接为 https://ropsten.opensea.io/assets/ 合约地址 /tokenId,比如查看加密猪 token Id 为 1 的链接地址为 https://ropsten.opensea.io/assets/0x×××/1,效果如图

image

交易加密猪有两种方式,一是定价销售(Fixed Price),二是在一定价格范围内进行拍卖(Auction)

以上就是加密猪的交易功能#

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.