Substrate是开发应用特定区块链 (Application Specific Blockchain )的快速开发框架。 与基于以太坊等公链开发的DApp相比,应用特定区块链是围绕单一应用特别构建的专用区块链, 因此具有最大的灵活性和最少的限制。本文将详细介绍如何使用Substrate框架快速实现一个简单的游戏 应用专用区块链。
本文将按以下顺序完成这个简单的游戏专用区块链的教程:
- 下载安装substrate
- 配置全新的substrate-node-template和 substrate-ui
- 开发用于游戏区块链的新的运行时
- 使用substrate-ui实时无分叉升级运行时
- 升级substrate-ui展示新的运行时的特性与功能
前序环节
在开始本教程之前,首先在计算机中安装以下软件:
接下来还需要克隆这两个软件仓库并进行相应的配置:
如果希望快速掌握区块链应用的开发,推荐汇智网的区块链应用开发系列教程, 内容涵盖比特币、以太坊、eos、超级账本fabric和tendermint等多种区块链, 以及 java、c#、go、nodejs、python、php、dart等多种开发语言
STEP 1:启动区块链
如果安装没有问题,现在可以启动一个substrate开发链了!在 substrate-node-template目录运行生成的可执行文件:
1 | ./target/release/substrate-node-template --dev |
如果在启动节点时碰到任何错误,你可能需要使用下面命令清理区块链数据文件:
1 | ./target/release/substrate-node-template purge-chain --dev |
一切正常的话,就可以看到它出块了!
要和区块链交互,你需要启动Substrate UI。进入substrate-ui目录然后运行:
1 | yarn run dev |
最后,在浏览器中访问http://localhost:8000
,你应该可以访问你的区块链了!
STEP 2:将Alice加入网络
Alice是硬编码在你的区块链创世块配置中的账户,这个账户是预充值的而且 是负责区块链升级的超级用户。
要访问Alice账户,在Substrate UI中进入Wallet,然后在Seed输入栏填写://Alice
:
如果一切正常的话,你现在可以进入Send Funds功能区,从Alice向Default账户转账。 可以看到Alice账户已经预充值,因此向Default账户转5000,然后等待绿色对号出现 并显示转账后Default的余额:
STEP 3:创建一个新的运行时模块
现在是时间创建我们自己的运行时(Runtime)模块了。
打开substrate-node-template文件夹,创建一个新文件:
1 | ./runtime/src/demo.rs |
首先需要在文件开头引入一些库:
1 | // Encoding library |
所有的模块都需要声明一个名为Trait的trait,它用来定义模块需要的 独有的类型。在这个教程中,我们的运行时模块没有自己的特殊类型,但是 会继承在balances模块中定义的类型(例如Balance):
1 | pub trait Trait: balances::Trait {} |
在这个例子中,我们将创建一个简单的抛硬币游戏。用户需要支付入门费 才可以玩游戏,也就是掷一次硬币,如果赢了就可以得到罐子中的东西。无论 结果如何,用户的进门费都会在开出结果后再放到罐子里,供后续用户赢取。
我们可以使用宏decl_storage
来定义模块需要跟踪的存储条目:
1 | decl_storage! { |
Rust中的宏用来生成其他代码,属于一种元编程。这里我们引入了一个宏 以及自定义的语法以便简化存储的定义并使其易懂。这个宏负责生成所有 与Substrate存储数据库交互的实际代码。
你可以看到在我们的存储中,有三个条目,其中两个负责跟踪Balance, 另一个跟踪Nonce。Payment的声明为可选值,因此无论是否初始化过它的值 都不会有问题。
接下来我们将需要定义分发函数:那些供用户调用我们的区块链系统的函数。 这个游戏有两个用户可以交互的函数:一个允许我们支付进门费,另一个 让我们开始玩游戏:
1 | decl_module! { |
现在我们已经搭建好模块的结构,可以添加这些函数的实现逻辑了。首先我们 添加初始化存储条目的逻辑:
1 | // This function initializes the `payment` storage item |
然后我们将编写play()
函数的实现代码:
1 | // This function is allows a user to play our coin-flip game |
好了!你看用Substrate构建新的运行时模块多么简单,作为参照,你可以和上述代码 的完整版本进行对比。
STEP 4:将新模块整合入Substrate运行时
要实际应用我们上面开发的模块,还需要告诉运行时这个模块的存在,这需要修改
./runtime/src/lib.rs
文件。
首先我们需要在项目中包含我们创建的模块文件:
1 | ... |
接下来,我们需要告诉运行时demo模块暴露的Trait:
1 | ... |
最后,我们需要在运行时构造函数中包含demo模块:
1 | construct_runtime!( |
为了在升级成功时更容易观察一些,我们可以同时升级运行时规范与实现的名字:
1 | /// This runtime version.\npub const VERSION: RuntimeVersion = RuntimeVersion { |
同样,你可以参考这个完整实现代码。
STEP 5:升级区块链
现在我们已经创建了一个新的运行时模块,是时候升级我们的区块链了。
为此首先我们需要将新的运行时编译为Wasm二进制文件。进入substrate-node-template 然后运行:
1 | ./scripts/build.sh |
如果上述命令成功执行,它将会更新文件./runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm
。
你可以回到Substrate UI,然后再Runtime Upgrade功能区,选择这个文件,然后点击upgrade按钮:
一切顺利的话,你可以在Substrate UI的顶部看到我们为运行时新起的名字:
STEP 6:与新模块交互
在这个教程的最后,我们可以试玩新创建的游戏。使用浏览器的控制台开始交互。
在Susbtrate UI页面中,按F12打开开发者控制台。我们需要借助于这个页面加载 的一些JavaScript库。
在可以玩游戏之前,我们需要使用一个账户初始化set_payment
。我们将以Alice
的名义调用这个函数。她会使用一个签名消息慷慨的初始化钱罐:
1 | post({ |
当这个调用完成后,你应当会看到{finalized: "..."}
,表示已经添加到区块链了。
可以通过查询钱罐中的余额来确认这一点:
1 | runtime.demo.pot.then(console.log) |
这应当会返回Number {1000}
。
STEP 7:更新Substrate UI
现在我们看到的都是在后台运行的,现在我们更新用户界面来展示这些变化。 让我们添加一个用户界面以便可以玩游戏。为此我们需要修改substrate-ui仓库。
打开./src/app.jsx
文件,在readyRender()
函数中,你会看到生成不同
UX组件的代码。例如,这个代码片段控制着我们刚用过的Runtime升级用户界面:
1 | class UpgradeSegment extends React.Component { |
我们可以以此为模板实现游戏界面。在文件的结尾添加下面的代码:
1 | class DemoSegment extends React.Component { |
this.player表示游戏用户上下文。我们可以利用它获取用户余额:
1 | runtime.balances.balance(this.player) |
并以该用户的身份提交交易:
1 | tx={{ |
类似于在开发者控制台中的方式,我们可以动态显示钱罐中的当前余额:
1 | <Label>Pot Balance |
唯一还需要我们做的事情,就是将这个组件加入到文件开头的App类:
1 | readyRender() { |
保存上述修改然后重新载入页面,你应当可以看到新的UI了!现在可以使用 Default账户来玩游戏:
这里你可以看到玩家输掉了游戏,这意味着他们的1000单位币存入了钱罐, 同时从他们的账户余额中扣除额外的1单位币交易费。
如果我们多尝试几次,最终玩家会赢得比赛,钱罐将恢复到开始的金额等待 下一个玩家:
原文链接:Creating Your First Substrate chain
汇智网翻译整理,转载请标明出处