本文章将会介绍如何开发一个区块链DApp版的todo list,学习如何从区块链里读写数据以及在此之上实现todo list的业务逻辑,同时掌握区块链的基本运行原理以及以太坊的智能合约。
注: 译文相对原文有所简化
Blockchain应用的运行原理
普通版Todo list
当你打开todo list网页的时候,你的浏览器会向web服务器发出请求,从服务器上获取所有todo list的代码和数据到本地渲染。
在服务器上会有这些文件及数据:
- 前端用的HTML\CSS\JavaScript
- 后端实现业务逻辑的代码
- 数据库(用于存储数据)
普通web应用的状态下,这个服务器是一个控制着所有代码和文件的完全中心化的实体。 对于服务器有完全权限的人(服务器主人或黑掉你服务器的人)可以随时修改服务器上的数据或者文件。
DApp版todo list
后端逻辑代码和用户数据直接部署在去中心化的区块链上。而客户端/前端(HTML/CSS/JavaScript这部分)的代码依然会像普通的应用一样部署在普通的服务器上,只是这个客户端会直接去链上读数据而不是平常的中心化服务器上读取数据。
区块链为何物?
区块链网络是由很多点对点互联的节点构成的分布式的网络。其中的每个节点都维护着这个网络的一份代码和数据。所有数据都包含在称为“区块”的记录集里面,并且这些块是前后相接链在一起的,从而组成了一条区块链。网络上所有节点确保这些区块数据是安全的不可篡改的,不像中心化服务器那样能随意更改。区块链可以存储数据,本质上来说它是一个数据库,同时是一个分布式网(多节点的网络)。
在此强调下一个点:你在用一个区块链应用时,你不单单是这个应用的user,你更是这个应用所在的链的user。因为应用本身不存储数据,但是那条链在存储数据。
智能合约是什么?
智能合约是部署在区块链上的功能代码,这些代码构造了链上的每个应用。我们的todo list要运行当然也是要用到智能合约来处理todo任务的获取、创建、更新(标记为已完成)。
我们可以通过Solidity语言来写智能合约(这种语言跟JavaScript有点相似)。智能合约代码是不可以更改的,一旦部署到链上,那这个部署的链上版本就无法再更新代码(平常的中心化服务器上的后端代码是可以更新的)。智能合约可以类比Web上的微服务,这种微服务从链上读写数据以及执行业务逻辑。这些服务是公开访问的,所有对这条链有权限的人都可以使用这些服务。
区块链版Todo List运行原理
重新理一下我们要做的东西:创建一个可以从链上读写数据的前端应用(使用的是Ethereum链),只要连上单个Ethereum节点就可以搭上这条链。我们使用Solidity来写这个todo list并且部署到链上。然后我们会用自己的以太钱包帐户来和这个todo list应用通信。
预览一下成果
UI操作跟普通版todo list是相似的逻辑,主要功能是列出任务、创建任务、标记完成。
1.png安装依赖
Ganache私有链
Ganache私有链可以模仿公有链的特性来作为本地开发环境。我推荐使用它来作为在以太坊开发中的私有链。在Ganache上可以部署智能合约、开发应用和运行测试。Windows、Mac、Linux上都有Ganache的桌面版和命令行版本。
2.png首先来安装一个Ganache,在这里 https://github.com/trufflesuite/ganache/releases 下载然后点击安装然后运行:
3.png好了,你现在运行有一条私有链,并且可以看到一些运行数据以及帐号列表,每个帐号都预设有100 ETH。一下子节省了很多时间,因为如果你是自己搭建私有链或者在以太的测试链上去开发应用,你就要手动创建这些帐号并且记入ETH到这些帐号上。再次感谢Ganache给了大大的方便。
Node.js
有了私有链,然后来配置一个开发智能合约的开发环境。首先需要的是Node的包管理器npm,你可以用以下命令来检查一下你有没有装node:
node -v
如果没装,那得去装一下先:https://nodejs.org
Truffle Framework
然后再来装的是 Truffle Framework (https://truffleframework.com),它用于提供以太智能合约开发的Solidity套件。
以下是Truffle Framework提供的功能:
-
<b>智能合约管理</b> - 用Solidity来写智能合约并且编译成可以在以太虚拟机(EVM)上运行的bytecode。
-
<b>自动化测试</b> - 针对代码用JavaScript或者Solidity写一些测试,之后就可以在任意一个Truffle配置的网络运行(包括公有链)。
-
<b>部署及迁移</b> - 写脚本来管理智能合约的部署和迁移。
-
<b>开发控制台</b> - Truffle控制台里可以使用JavaScript语法调用智能合约,任意配置了的网络都可以。
-
<b>脚本运行器</b> - 允许使用JavaScript来写脚本,这些脚本可以运行在公有链上。
-
<b>客户端开发</b> - 配置truffle项目来托管你的客户端。
可以使用npm来安装Truffle。 注意:最好按下面的版本来安装,不然会有版本兼容问题(对于本教程的代码)。
Metamask 以太钱包
目前大部分的浏览器都无法直接连接到区块链网络上,但是扩展可以。
安装一下谷歌扩展: https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn?hl=en
这个扩展可以管理我们的个人以太钱包,发送ETH来交易。
4.png初始化项目
首先创建项目目录
$ mkdir eth-todo-list
$ cd eth-todo-list
使用truffle初始化
$ truffle init
初始化成功之后在eth-todo-list这个目录下会生成很多文件。然后现在需要创建一个package.json文件来指定需要安装的依赖:
$ touch package.json
复制以下的配置来引导依赖:
{
"name": "eth-todo-list",
"version": "1.0.0",
"description": "Blockchain Todo List Powered By Ethereum",
"main": "truffle-config.js",
"directories": {
"test": "test"
},
"scripts": {
"dev": "lite-server",
"test": "echo \"Error: no test specified\" && sexit 1"
},
"author": "gregory@dappuniversity.com",
"license": "ISC",
"devDependencies": {
"bootstrap": "4.1.3",
"chai": "^4.1.2",
"chai-as-promised": "^7.1.1",
"chai-bignumber": "^2.0.2",
"lite-server": "^2.3.0",
"nodemon": "^1.17.3",
"truffle": "5.0.2",
"truffle-contract": "3.0.6"
}
}
然后安装依赖:
$ npm install
安装完之后,整个目录结构应该是这样的:
<center>
<img src="https://cdn.blostack.com/other/XrCY1gpfjYGUX4IBpYRVn9JLqicUvKDoPKXrElD9.png" style="margin:0 auto;width:40%;">
</center>
-
<b>contracts 目录</b>: 放所有智能合约文件,里面已经有一个迁移文件(Migrations.sol)
-
<b>migrations 目录</b>: 放置所有迁移文件,跟普通的web开发框架里的migrations文件一样是用于修改数据库状态。
-
<b>node_modules 目录</b>: 依赖模块的目录
-
<b>test 目录</b>: 智能合约测试文件目录
-
<b>truffle-config.js 文件</b>: Truffle项目主配置文件
现在来开发管理任务列表的智能合约,先创建一下文件:
$ touch ./contracts/TodoList.sol
这个sol文件就是写合约代码的地方,文件头先声明一下语言版本:
pragma solidity ^0.5.0;
然后声明智能合约:
pragma solidity ^0.5.0;
contract TodoList {
// Code goes here...
}
以上创建了一个叫 <b>TodoList</b> 的合约(应该很容易明白,跟声明一个类差不多的语法),合约代码会写在这个合约类里面。现在要做的就是记录这个todoList里面的任务的数量,声明一个taskCount的变量即可:
pragma solidity ^0.5.0;
contract TodoList {
uint taskCount;
}
这里的 taskCount
是一种叫“状态变量”的特殊变量,状态变量会存储到链上,并且在整个智能合约类中都可以被访问使用。现在初始化一下这个变量:
pragma solidity ^0.5.0;
contract TodoList {
uint taskCount = 0;
}
我们可以使用 public
修饰符来保证可以在合约外访问这个变量,Solidity会为 taskCount
变量自动创建taskCount()
函数来让外部访问到。当你在控制台、客户端应用、测试文件中和智能合约进行交互时这种函数会很好用。
现在来编译一下这些合约并且确保没有报错:
$ truffle compile
刚我们写了第一个以太坊的智能合约。编译完之后可以看到多出了一个这样的文件: ./build/contracts/TodoList.json
, 这是智能合约 ABI 文件,全称是"Abstract Binary Interface"。这个文件有很多用途,其中比较重要的两个作用:
-
文件包含了由Solidity智能合约代码编译出来的字节码版本,这种字节码可以在以太坊虚拟机(EVM)上运行
-
文件包含了可以被JavaScript应用等外部客户端访问的智能合约函数
下一步目标是用Truffle控制台来访问刚写的那个智能合约。首先来做以下的工作:
-
更新下项目配置文件,指定连接到我们开始时运行的Ganache网络。
-
创建一个迁移脚本,作用是让Truffle知道怎么部署智能合约到刚指定的Ganache链上。
-
运行这个刚写的迁移脚本部署合约到链上
第一步
来配置网络,找到 truffle-config.js 这个文件,复制以下代码:
module.exports = {
networks: {
development: {
host: "127.0.0.1",
port: 7545,
network_id: "*" // Match any network id
}
},
solc: {
optimizer: {
enabled: true,
runs: 200
}
}
}
7545是
Ganache
的默认端口,如果你修改过Ganache
的端口,那配置文件这里的端口也要相关修改。 host同理
第二步
创建迁移脚本,部署智能合约到链上。在项目根目录下创建迁移文件:
$ touch migrations/2_deploy_contracts.js
这个文件的作用是其实跟普通web框架的数据库迁移文件一样。区块链本质还是一个数据库,每次创建一个智能合约时就是在改变这个数据库的状态。
注意:如果有多个迁移文件,一定要按顺序编号好,这样Truffle才会按编号的正确顺序去执行每个文件。现在我们这个文件应该会是以下内容:
var TodoList = artifacts.require("./TodoList.sol");
module.exports = function(deployer) {
deployer.deploy(TodoList);
};
应该都看得懂,先require进来,然后运行的时候会自动deploy这个智能合约。运行迁移的命令:
$ truffle migrate
运行完后智能合约就成功部署到我们这个私有链上了。然后我们开一个console来调用这个智能合约。
$ truffle console
在console里我们可以试下能不能读取到合约里面的 taskCount
变量:
todoList = await TodoList.deployed()
这里的TodoList
变量是我们在迁移文件里创建的。
(由于篇幅较长,分上下两篇,上篇到此结束)
微信搜索公众号: blostack 加入我们的微信群关注更多技术动态
网友评论