Substrate入门指南(一)
安装运行环境
跟随下列步骤安装substrate的运行环境(也可以参考这个链接):安装Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
随后选择
2) Customize installation
在随后的 Default toolchain? (stable/beta/nightly/none)
输入 nightly
再选择1) 开始安装
安装完成后,运行 source $HOME/.cargo/env 添加rust的环境变量
安装完成后,输入 rustc –version,此时应该有版本号输出下载substrate代码
git clone -b v2.0.0 --depth 1 https://github.com/substrate-developer-hub/substrate-node-template
安装编译工具
source ~/.cargo/env rustup update nightly rustup update stable rustup target add wasm32-unknown-unknown --toolchain nightly
运行你的第一个区块链
进入刚才clone的代码目录,随后执行编译命令cd substrate-node-template/ cargo build --release
如果遇到更新crates.io index缓慢的问题,可以参考这个链接换源。
换源后,需要注意添加环境变量 CARGO_HTTP_MULTIPLEXING=false 否则下载会失败。
其它镜像可以参考这个链接如果遇到error: linker
cc
not found的错误,可以通过运行yum groupinstall “Development Tools” 安装Linux的开发组件来解决。如果遇到Unable to find libclang的错误,运行下列命令安装clang(clang必须6.0以上)
yum install centos-release-scl
yum install llvm-toolset-7.0
scl enable llvm-toolset-7.0 ‘bash’
clang –version如果发生其它编译错误,可以用命令dmesg | egrep -i ‘killed process’查看是否是内存不够导致的。
启动区块链
./target/release/node-template --dev --tmp
控制台如果输出Warning: Low open file descriptor limit configured for the process,可以通过ulimit -n 10000来解决。
如果看到如下输出,恭喜你,你创建了你人生的第一个区块链了。
让别人加入到你的区块链
安装密钥工具
cargo install --force subkey --git https://github.com/paritytech/substrate --version 2.0.0
生成sr25519
subkey generate --scheme sr25519
随后复制生成的secret phrase文本
生成ed25519
subkey inspect --scheme ed25519 "之前复制的secret phrase"
创建配置文件
./target/release/node-template build-spec --disable-default-bootnode --chain local > customSpec.json
随后打开customSpec.json,找到Aura和Grandpa部分
将之前我们生成的sr25519的Address替换Aura的authorities列表,将ed25519的Address替换Grandpa的authorities列表最后,生成加密的配置文件customSpecRaw.json,用于分发配置给其它节点
./target/release/node-template build-spec --chain=customSpec.json --raw --disable-default-bootnode > customSpecRaw.json
启动根节点
./target/release/node-template \ --base-path /tmp/node01 \ --chain ./customSpecRaw.json \ --port 30333 \ --ws-port 9944 \ --rpc-port 9933 \ --telemetry-url 'wss://telemetry.polkadot.io/submit/ 0' \ --validator \ --rpc-methods=Unsafe \ --name MyNode01 \ --rpc-cors all
这里需要注意的几点:
–base-path 指向数据文件存放路径
–chain 参数指向刚刚生成的配置文件
–name 自定义节点名
–rpc-cors all 允许跨域访问通过https://polkadot.js.org/apps/访问自己的节点
在custom endpoint中输入域名(注意如果不是localhost的话,那么必须用wss协议,否则浏览器会限时访问)。
但是使用wss就要求域名配置ssl证书,这里不推荐用自注册的证书,有可能会连接拒绝。下面是nginx的配置参考。
可以看到当接受外部443的连接请求后,nginx会转发到localhost的9944,也即之前启动命令里的–ws-port所指定的端口号。配置成功后,我们就能看到如下界面:
如果想要重新配置,或者配置过程中发生错误,我们也可以用如下命令清除之前生成的数据
./target/release/node-template purge-chain –base-path 数据路径添加密钥
通过菜单页面的Developer > RPC Calls,打开RPC Calls页面,选择author > insertKey,提交AURA和GRANDPA的secret phrase和public key这时我们再看Explorer页面,应该能看到这个节点不断生成的Block了
添加子节点
将customSpecRaw.json分发给子节点的电脑,随后执行下列代码:./target/debug/node-template \ --base-path /tmp/node02 \ --chain ./customSpecRaw.json \ --port 30334 \ --ws-port 9945 \ --rpc-port 9934 \ --telemetry-url 'wss://telemetry.polkadot.io/submit/ 0' \ --validator \ --rpc-methods=Unsafe \ --name MyNode02 \ --bootnodes /ip4/<IP Address>/tcp/<Port>/p2p/<Peer ID>
需要注意–bootnodes的参数,IP Address是根节点的IP地址,Peer ID是根节点在启动时的,Local node identity
此外,如果发现block一直没有finalized的话,那是因为在插入GRANDPA Key后,要生效需要重启boot节点。
这时当我们打开Explorer的Node Info页面时,如果你看到如下页面中的total peers为1时,恭喜你,分发节点成功了,你创建了属于你的区块链。
搭建自己的前端
前面我们用的是polkadot的前端系统,在实际应用中,肯定会有很多定制化的需求,可以参考这个官方项目,或者如果你更熟悉Vue,可以参考如下示例。克隆一个你喜欢的Vue框架,例如vue-element-admin
在package.json中的dependencies节点,添加对polkadot的类库依赖
"@polkadot/api": "^2.2.1", "@polkadot/extension-dapp": "^0.34.1", "@polkadot/types": "^1.34.1", "@polkadot/ui-keyring": "^0.58.1", "@polkadot/ui-settings": "^0.58.1", "@polkadot/util": "^3.4.1", "@polkadot/util-crypto": "^3.4.1",
运行npm install
添加config.js文件和connection.js文件在src根目录下
config.js
export const default_endpoint = "wss://区块链地址";
connection.js
import { default_endpoint } from "./config.js"; const endpoint = localStorage.getItem("endpoint"); if (!endpoint || typeof endpoint !== "string" || endpoint.indexOf("ws") !== 0) { localStorage.setItem("endpoint", default_endpoint); } const { ApiPromise, WsProvider } = require("@polkadot/api"); const wsProvider = new WsProvider(localStorage.getItem("endpoint")); let api = ApiPromise.create({ provider: wsProvider, types: { // mapping the actual specified address format Address: 'AccountId', // mapping the lookup LookupSource: 'AccountId' } }); export default api;
添加api接口文件,里面可以写各种对Substrate的接口调用
```
export async function getBlockNumber(api) {
const block = await api.rpc.chain.getBlock();
return block.block.header.number.toNumber();
}
export async function getAccountInfo(api) {
const ADDR = '5CB7ZJioWA1EBibJKoQbxkyCupnEB1oQ2MFrRFvDxFLqTVMa';
const now = await api.query.timestamp.now();
// Retrieve the account balance & nonce via the system module
const { nonce, data: balance } = await api.query.system.account(ADDR);
console.log(`${now}: balance of ${balance.free} and a nonce of ${nonce}`);
// Subscribe to balance changes for our account
const unsub = await api.query.system.account(ADDR, ({ nonce, data: balance }) => {
console.log(`free balance is ${balance.free} with ${balance.reserved} reserved and a nonce of ${nonce}`);
});
}
```
6) 最后,我们可以在页面中直接调用接口,获取相应数据,例如
```
import api from "@/connection.js";
import { getBlockNumber, getAccountInfo, getChainInfo } from "@/api/polkadot";
export default {
name: 'Dashboard',
computed: {
...mapGetters(['name'])
},
created() {
api.then((api) => {
getBlockNumber(api).then((blockNumber) => {
this.blocknumber = blockNumber;
});
getAccountInfo(api);
});
}
}
```
7) 关于详细的Substrate API介绍,可以查看[官网链接](https://polkadot.js.org/docs/api)