在本教程中, 您将学习如何使用 Tendermint 和 Lotionjs 轻松将 "权益证明" 区块链应用作为两个验证者节点部署至 IBM 容器.
学习目标
学习如何使用 Tendermint 和 Lotionjs 将 "权益证明" 区块链应用作为两个验证者节点部署至 IBM 容器
完成本教程所需时间
大约 60 分钟.
前提条件
您需要安装以下软件:
IBM Cloud CLI, 用于管理 IBM Cloud 中的应用, 容器, 基础架构, 服务和其他资源的命令行界面
Docker https://docs.docker.com/install/ , 使用容器开发, 部署和运行应用的平台
Kubectl, 用于在 Kubernetes 上部署和管理应用的命令行工具
背景
试用测试版 IBM Blockchain Starter Plan
全新的 IBM Blockchain Starter Plan 是将业务网络部署到 IBM Cloud 的便捷途径.
在该 Starter Plan 推出之前, 您必须将业务网络部署到本地运行的 Hyperledger Fabric 实例上. 而现在, 您可以选择直接在 IBM Cloud 上为企业或初创公司构建和部署业务网络.
试用全新的 Starter Plan! 然后, 将样本网络部署至 Starter Plan 实例.
区块链技术是自从因特网诞生以来最伟大的技术创新之一. 因特网支持信息的自由流动, 而区块链则支持价值的无障碍流动. 在应用密码学方面, 前所未有的大量研究正在如火如荼地展开. 各行各业的企业都在将区块链技术应用于真实的业务用例.
区块链也是一项崭新的技术. 快速开发区块链应用原型并在云端运行往往困难重重. Tendermint 可用于快速创建区块链应用, 因为它可处理位于底层的区块链层 (例如, 网络和共识), 同时还可通过 ABCI(应用区块链接口) 聚焦应用层. 在本教程中, 我将向您展示如何使用 Tendermint 和 Lotionjs 轻松创建区块链聊天应用, 并将其部署至 IBM Cloud.
什么是 Tendermint?
简而言之, Tendermint 是可用于在任何分布式计算平台中实现拜占庭容错 (BFT) 的软件. 从管理基础架构到设计分布式数据库, 都可使用 Tendermint.Tendermint 基于两个重要的技术组件而构建:
共识引擎 (也称为 Tendermint 核心) 可通过 "权益证明" 共识确保在每台机器中按相同顺序记录每个事务.
ABCI(应用区块链接口)支持以任何编程语言来处理事务.
Tendermint 具有以下特性:
拜占庭容错: Tendermint 最高可容忍三分之一的机器出现任意故障. 这包括明确的恶意行为.
状态机复制: Tendermint 可复制以任何编程语言编写的确定性状态机.
安全的 P2P: 通过 Tendermint 中经过认证的加密系统来保护 Gossip 协议和对等节点发现.
闪电般的速度: Tendermint 支持每秒数千个事务, 1000 毫秒延迟.
什么是 Lotionjs?
Lotion 是在 JavaScript 中创建区块链应用的一种快速而有趣的方法. 它是基于 Tendermint 使用 ABCI 协议构建的.
1
设置项目
创建新目录并导航至此目录:
- $ mkdir blockchain
- $ cd blockchain
安装所需的库:
- $ NPM i lotion --save
- $ NPM i dotenv --save
- 2
创建 2 个验证者节点的私有密钥和创始文件
创建创始文件: touch genesis.JSON
将初始内容填充到 genesis.JSON 中:
- {
- "genesis_time": "0001-01-01T00:00:00Z",
- "chain_id": "name",
- "validators": [
- ],
- "app_hash": ""
- }
生成 2 个验证者节点的密钥:
- $ ./node_modules/lotion/bin/tendermint gen_validator> privkey0.JSON
- $ ./node_modules/lotion/bin/tendermint gen_validator> privkey1.JSON
私有密钥类似如下, 公用密钥和私有密钥是随机生成的:
- {
- "address": "B809574EC51377DE48454094BF3302989CBB50A9",
- "pub_key": {
- "type": "ed25519",
- "data": "8A049817BA6D1B065C30D927A529AAFA7147BE0D147E1CCD7A25FAADBE80C8D0"
- },
- "priv_key": {
- "type": "ed25519",
- "data": "57BAFDD6136E1140FA9F906313BF2CFC75802F044704DD7AAF30BC1010E6519C8A049817BA6D1B065C30D927A529AAFA7147BE0D147E1CCD7A25FAADBE80C8D0"
- }
- }
仅复制公用密钥信息, 并将其粘帖到 genesis.JSON 中. 添加两个验证者后, 将类似如下:
- {
- "genesis_time": "0001-01-01T00:00:00Z",
- "chain_id": "name",
- "validators": [
- {
- "pub_key": {
- "type": "ed25519",
- "data": "8A049817BA6D1B065C30D927A529AAFA7147BE0D147E1CCD7A25FAADBE80C8D0"
- },
- "power": 10,
- "name": "saif"
- },
- {
- "pub_key": {
- "type": "ed25519",
- "data": "5FD1FBF59759E50BD1C23911E832198AB78A4F7E6F1F23A64AAFEC5992608CA8"
- },
- "power": 20,
- "name": "prerna"
- }
- ],
- "app_hash": ""
- }
- 3
构建验证者 1
创建 node1 文件夹: mkdir node1
浏览至 node1 目录: cd node1
安装所需的库:
- $ NPM i lotion --save
- $ NPM i dotenv --save
将先前生成的 genesis.JSON 和 privkey0.JSON 复制到 node1 文件夹.
创建 node1 的环境文件: $ touch .env-node1
对 node1.JS 的内容进行编码:
LOTION_HOME="./.lotion_node1"
创建 node1.JS: $ touch node1.JS
对 node1.JS 的内容进行编码:
- require('dotenv').config({path: ".env-node1"});
- let lotion = require('lotion')
- let App = lotion({
- genesis: './genesis.json',
- tendermintPort: 30090,
- initialState: { messages: [] },
- p2pPort: 30092,
- logTendermint: true,
- keys: 'privkey0.json',
- peers: ['workernode2:30092']
- })
- App.use((state, tx,chainInfo) => {
- if (typeof tx.sender === 'string' && typeof tx.message === 'string') {
- state.messages.push({ sender: tx.sender, message: tx.message })
- }
- })
- App.listen(3000).then(({ GCI }) => {
- console.log(GCI)
- })
创建 Dockerfile: $ touch Dockerfile
对 Dockerfile 的内容进行编码:
- FROM node:carbon
- WORKDIR /usr/src/App
- COPY package*.JSON ./
- COPY privkey0.JSON ./
- COPY .env-node1 ./
- RUN NPM install
- COPY ..
- EXPOSE 30090 30092
- CMD [ "node", "node1.js" ]
- 4
构建验证者 2
创建 node2 文件夹: mkdir node2
浏览至 node2 目录: cd node2
安装所需的库:
- $ NPM i lotion --save
- $ NPM i dotenv --save
将先前生成的 genesis.JSON 和 privkey0.JSON 复制到 node2 文件夹.
创建 node2 的环境文件: $ touch .env-node2
对 node2.JS 的内容进行编码:
LOTION_HOME="./.lotion_node2"
创建 node2.JS: $ touch node1.JS
对 node2.JS 的内容进行编码:
- require('dotenv').config({path: ".env-node2"});
- let lotion = require('lotion')
- let App = lotion({
- genesis: './genesis.json',
- tendermintPort: 30090,
- initialState: { messages: [] },
- p2pPort: 30092,
- logTendermint: true,
- keys: 'privkey1.json',
- peers: ['workernode1:30092']
- })
- App.use((state, tx,chainInfo) => {
- if (typeof tx.sender === 'string' && typeof tx.message === 'string') {
- state.messages.push({ sender: tx.sender, message: tx.message })
- }
- })
- App.listen(3000).then(({ GCI }) => {
- console.log(GCI)
- })
创建 Dockerfile: $ touch Dockerfile
对 Dockerfile 的内容进行编码:
- FROM node:carbon
- WORKDIR /usr/src/App
- COPY package*.JSON ./
- COPY privkey0.JSON ./
- COPY .env-node1 ./
- RUN NPM install
- COPY ..
- EXPOSE 30090 30092
- CMD [ "node", "node2.js" ]
- 5
将这两个验证者节点部署到 IBM Cloud 上
注册 IBM Cloud.
安装 Cloud Foundry CLI.
安装 IBM Cloud CLI.
安装 Kubernetes CLI.
浏览至 node1 目录: $ cd node1
构建 Docker 镜像:
$ docker build -t node1 .
转至 IBM Cloud 控制台.
导航至 Containers:
点击查看大图
单击 Create Cluster:
点击查看大图
命名您的集群, 并创建一个集群; 等待几分钟, 以便完全部署此集群. 完全部署后, 单击此集群以查看已部署集群的概述:
点击查看大图
单击左侧导航中的 Access, 遵循指示信息进行操作.
安装容器服务插件:
$ bx plugin install container-service -r Bluemix
登录到您的 IBM Cloud 帐户:
- $ bx login -a https://api.eu-de.bluemix.net
- $ bx cs region-set eu-central
在 CLI 中设置集群的环境:
获取设置环境变量的命令, 并下载 Kubernetes 配置文件:
$ bx cs cluster-config NameOfYourCluster
设置 KUBECONFIG 环境变量. 将先前命令的输出复制并粘帖到您的终端内.
列出您的工作节点, 验证您是否可连接到自己的集群:
$ kubectl get nodes
转至 IBM Cloud Container Registry.
选择首个名称空间的名称, 并创建该名称空间.
$ bx cr namespace-add <my_namespace>
将本地 Docker 守护程序记录到 IBM Cloud Container Registry 中: $ bx cr login
选择存储库和用于识别镜像的标签. 在本教程的其余部分使用相同的存储库和标签.
$ docker tag node1 <registry>/<my_namespace>/node1:latest
推送镜像.
$ docker push <registry>/<my_namespace>/node1:latest
验证您的镜像是否位于私有注册表中: $ bx cr image-list
既然您的容器已部署到 IBM 容器上, 是时候使用 Kubernetes 来运行一些 pod 了. 使用复制 / 粘帖将镜像名称从注册表的私有名称更改为其他名称.(位于 service-deployment.YAML 文件中的镜像属性将与私有注册表中的镜像名称相同.)
- apiVersion: extensions/v1beta1
- kind: Deployment
- metadata:
- name: tendermintnodeone # give any name
- spec:
- replicas: 1
- template:
- metadata:
- name: tendermintnodeone
- labels:
- run: tendermint1
- spec:
- containers:
- - name: saif1cluster
- image: "<registry>/<my_namespace>/node1:latest" # your registry name
- imagePullPolicy: Always
- ---
- apiVersion: v1
- kind: Service
- metadata:
- name: my-service-tendermint-11 # give a service name
- labels:
- run: tendermint1
- spec:
- type: NodePort
- selector:
- run: tendermint1
- ports:
- - protocol: TCP
- name: tendermint1
- port: 30090
- nodePort: 30090
- - protocol: TCP
- name: port
- port: 30092
- nodePort: 30092
配置 Kubernetes 以创建 pod, 服务和部署:
$ kubectl create -f service-deployment.YAML
删除所有部署:
$ kubectl delete deployments --all
删除所有服务:
$ kubectl delete services --all
访问 pod 和日志:
- $ kubectl get pods
- $ kubectl logs podname
访问 Tendermint RPC API:http://workerip:30092
对 node2 重复相同的步骤.
6
创建轻量级客户端以在区块链上执行读 / 写操作
安装 lotion-connect:
$ NPM install lotion-connect --save
创建 write.JS:
$ touch read-write.JS
对 read-write.JS 的内容进行编码:
- let { connect } = require('lotion-connect')
- async function main() {
- let { state, send } = await connect(null, {
- genesis: require('./genesis.json'),
- nodes: [ 'ws://wordernode1:30092','ws://wordernode2:30092' ]
- })
- console.log(await state)
- console.log(await send({ "sender": 'saif',"message":"himom" }))
- process.exit();
- }
- main()
结束语
Tendermint 便于业务开发人员编写区块链应用, 而 IBM Cloud 则简化了此类应用的部署和操作.
了解更多信息
Tendermint 文档
创建端到端的 Tendermint 区块链聊天应用
Tendermint 区块链聊天应用 GitHub 存储库 https://github.com/SaifRehman/tendermint-chat-app
后续行动
既然您已将区块链应用部署至 IBM Cloud, 就请阅读由 Steve Perry 编写的热门系列教程 Hyperledger Composer 基础, 学习如何使用 Hyperledger Composer 从头开始创建业务网络.
查阅众多 Code Pattern, 它们为解决区块链技术中遇到的复杂问题提供了路线图, 并包括架构图, 代码存储库和其他阅读材料.
访问区块链开发人员中心. 可以在这里获得开发和部署商业区块链解决方案的免费工具和教程, 以及代码和社区支持.
来源: http://www.ibm.com/developerworks/cn/cloud/library/cl-create-blockchain-chat-app-tendermint-ibm-cloud/index.html