注意:
本系列文章遇到的问题都可以参考查找 官方文档 或 本系列问题总结!
FISCO-BCOS 及 WeBase 问题记录
FISCO-BCOS 官方文档
WeBase 官方文档
节点搭建的方法建议使用build_chain
详情可以参考本文节点搭建部分
wget https://www.fisco.com.cn/cdn/webase/releases/download/v1.3.1/webase-front.zip
unzip webase-front.zip
cd webase-front
将节点所在目录/root/fisco/nodes/127.0.0.1/sdk
下的ca.crt、node.crt和node.key
文件拷贝到/root/webase-front/conf
下
启动: bash start.sh
停止: bash stop.sh
检查: bash status.sh
http://localhost:5002/WeBASE-Front
一键部署可以在 同机 快速搭建WeBASE管理台环境,方便用户快速体验WeBASE管理平台。
一键部署会搭建:节点(FISCO-BCOS 2.0+)、管理平台(WeBASE-Web)、节点管理子系统(WeBASE-Node-Manager)、节点前置子系统(WeBASE-Front)、签名服务(WeBASE-Sign)。其中,节点的搭建是可选的,可以通过配置来选择使用已有链或者搭建新链。一键部署架构如下:
环境 | 版本 |
---|---|
Java | JDK8或以上版本 |
MySQL | MySQL-5.6或以上版本 |
Python | Python3.4+ |
PyMySQL | 使用python3时需安装 |
wget https://github.com/WeBankFinTech/WeBASELargeFiles/releases/download/v1.3.1/webase-deploy.zip
unzip webase-deploy.zip
cd webase-deploy
① mysql数据库需提前安装,已安装直接配置即可,还未安装请参看 本文数据库部署部分 或 官方文档的数据库部署部分;
② 修改配置文件(vim common.properties),没有变化的可以不修改;
③ 一键部署支持使用已有链或者搭建新链。通过参数”if.exist.fisco”配置是否使用已有链,以下配置二选一即可:
如果不使用一键部署搭建新链,可以参考FISCO BCOS官方文档搭建 FISCO BCOS部署流程;
④ 服务端口不能小于1024。
common.properties 中需要修改的内容有
- 对数据库进行相关修改
- 使用现有链,对
if.exist.fisco
进行修改- 对
fisco.dir
和node.dir
进行修改- 对
node.counts
进行修改
补充说明:
- 对于
fisco.dir
需要选择路径下有start_all.sh
脚本以及sdk文件(其中包含ca.crt, node.crt and node. Key
)- 对于
node.dir
选择fisco.dir
下面任意node中的就行,只要这个node时链接WeBASE-Front,并且路径下包含conf文件(其中包含ca.crt, node.crt and node. Key
)
下面为本人修改后的内容实例:
# Webase Subsystem Version (v1.1.0 or above)
webase.web.version=v1.3.1
webase.mgr.version=v1.3.1
webase.sign.version=v1.3.1
webase.front.version=v1.3.1
# 对数据库进行了修改配置
# Mysql database configuration of WeBASE-Node-Manager
mysql.ip=127.0.0.1
mysql.port=3306
mysql.user=root
mysql.password=123456
mysql.database=webasenodemanager
# Mysql database configuration of WeBASE-Sign
sign.mysql.ip=localhost
sign.mysql.port=3306
sign.mysql.user=dbUsername
sign.mysql.password=dbPassword
sign.mysql.database=webasesign
# H2 database name of WeBASE-Front
front.h2.name=webasefront
# WeBASE-Web service port
web.port=5000
# WeBASE-Node-Manager service port
mgr.port=5001
# WeBASE-Front service port
front.port=5002
# WeBASE-Sign service port
sign.port=5004
node.listenIp=127.0.0.1
# Node p2p service port
node.channelPort=20200
# Node rpc service port
node.rpcPort=8545
# Encrypt type (0: standard, 1: guomi)
encrypt.type=0
# Use existing chain or not (yes/no)
# 使用现有链,对`if.exist.fisco`进行修改
if.exist.fisco=yes
# Configuration is required when using the existing chain
# The path of the existing chain, the path of the start_all.sh script
# Under the path, there should be a SDK directory where the SDK certificates (ca.crt, node.crt and node. Key) are stored
# 对`fisco.dir`和`node.dir`进行修改
fisco.dir=/root/fisco/nodes/127.0.0.1
# Absolute path of the connected node in WeBASE-Front
# Under the path, there is a conf directory where node certificates (ca.crt, node.crt and node. Key) are stored
node.dir=/root/fisco/nodes/127.0.0.1/node0
# Configuration required when building a new chain
# Fisco-bcos version
fisco.version=2.4.1
# Number of building nodes (two by default)
# 对`node.counts`进行修改
node.counts=4
WeBASE默认端口号为5000,在阿里云安全组规则添加5000端口
至于如何添加安全组规则可以参考 本文添加安全组规则部分
部署之后会自动启动所有服务
python3 deploy.py installAll
如果服务器重启之后,需再次启动节点,然后先运行上面命令进行任务部署(如果不是想重新配置而只是部署直接全程n)
如果在此过程中遇到问题可以参考此文 -> FISCO-BCOS 及 WeBase 问题记录
其他命令:
# 启动所有服务:
python3 deploy.py startAll
# 停止所有服务:
python3 deploy.py stopAll
# 服务部署后,如果需要单独启停,可以使用以下命令:
启动FISCO-BCOS节点: python deploy.py startNode
停止FISCO-BCOS节点: python deploy.py stopNode
启动WeBASE-Web: python deploy.py startWeb
停止WeBASE-Web: python deploy.py stopWeb
启动WeBASE-Node-Manager: python deploy.py startManager
停止WeBASE-Node-Manager: python deploy.py stopManager
启动WeBASE-Sign: python deploy.py startSign
停止WeBASE-Sign: python deploy.py stopSign
启动WeBASE-Front: python deploy.py startFront
停止WeBASE-Front: python deploy.py stopFront
备注:
- 部署脚本会拉取相关安装包进行部署,需保持网络畅通。
- 首次部署需要下载编译包和初始化数据库,重复部署时可以根据提示不重复操作
- 部署过程出现问题可以查看常见问题解答
http://{deployIP}:{webPort}
示例:http://localhost:5000
备注:
- 部署服务器IP和管理平台服务端口需对应修改,网络策略需开通
- WeBASE管理平台使用说明请查看使用手册(获取WeBASE管理平台默认账号和密码,并初始化系统配置)
# 用户名
admin
# 密码
Abcd1234
首次登录需要新增节点前置
ip:自己的ip
前置端口:5002
所属机构:自己随意
修改后密码:Abc123456(随意)
可以在用户管理中新建WeBASE的管理员用户,但是这个不是链上用户,链上用户需要在私钥管理里新增。
在合约IDE中新建两个文件:Test和Table,因为Table是对底层的封装,可以实现CRUD,Test则需要引用Table,所以需要这两个文件。
Test.sol
pragma solidity ^0.4.24;
import "./Table.sol";
contract Asset {
// event
event RegisterEvent(int256 ret, string account, uint256 asset_value);
event TransferEvent(int256 ret, string from_account, string to_account, uint256 amount);
constructor() public {
// 构造函数中创建t_asset表
createTable();
}
function createTable() private {
TableFactory tf = TableFactory(0x1001);
// 资产管理表, key : account, field : asset_value
// | 资产账户(主键) | 资产金额 |
// |-------------------- |-------------------|
// | account | asset_value |
// |---------------------|-------------------|
//
// 创建表
tf.createTable("t_asset", "account", "asset_value");
}
function openTable() private returns(Table) {
TableFactory tf = TableFactory(0x1001);
Table table = tf.openTable("t_asset");
return table;
}
/*
描述 : 根据资产账户查询资产金额
参数 :
account : 资产账户
返回值:
参数一: 成功返回0, 账户不存在返回-1
参数二: 第一个参数为0时有效,资产金额
*/
function select(string account) public constant returns(int256, uint256) {
// 打开表
Table table = openTable();
// 查询
Entries entries = table.select(account, table.newCondition());
uint256 asset_value = 0;
if (0 == uint256(entries.size())) {
return (-1, asset_value);
} else {
Entry entry = entries.get(0);
return (0, uint256(entry.getInt("asset_value")));
}
}
/*
描述 : 资产注册
参数 :
account : 资产账户
amount : 资产金额
返回值:
0 资产注册成功
-1 资产账户已存在
-2 其他错误
*/
function register(string account, uint256 asset_value) public returns(int256){
int256 ret_code = 0;
int256 ret= 0;
uint256 temp_asset_value = 0;
// 查询账户是否存在
(ret, temp_asset_value) = select(account);
if(ret != 0) {
Table table = openTable();
Entry entry = table.newEntry();
entry.set("account", account);
entry.set("asset_value", int256(asset_value));
// 插入
int count = table.insert(account, entry);
if (count == 1) {
// 成功
ret_code = 0;
} else {
// 失败? 无权限或者其他错误
ret_code = -2;
}
} else {
// 账户已存在
ret_code = -1;
}
emit RegisterEvent(ret_code, account, asset_value);
return ret_code;
}
/*
描述 : 资产转移
参数 :
from_account : 转移资产账户
to_account : 接收资产账户
amount : 转移金额
返回值:
0 资产转移成功
-1 转移资产账户不存在
-2 接收资产账户不存在
-3 金额不足
-4 金额溢出
-5 其他错误
*/
function transfer(string from_account, string to_account, uint256 amount) public returns(int256) {
// 查询转移资产账户信息
int ret_code = 0;
int256 ret = 0;
uint256 from_asset_value = 0;
uint256 to_asset_value = 0;
// 转移账户是否存在?
(ret, from_asset_value) = select(from_account);
if(ret != 0) {
ret_code = -1;
// 转移账户不存在
emit TransferEvent(ret_code, from_account, to_account, amount);
return ret_code;
}
// 接受账户是否存在?
(ret, to_asset_value) = select(to_account);
if(ret != 0) {
ret_code = -2;
// 接收资产的账户不存在
emit TransferEvent(ret_code, from_account, to_account, amount);
return ret_code;
}
if(from_asset_value < amount) {
ret_code = -3;
// 转移资产的账户金额不足
emit TransferEvent(ret_code, from_account, to_account, amount);
return ret_code;
}
if (to_asset_value + amount < to_asset_value) {
ret_code = -4;
// 接收账户金额溢出
emit TransferEvent(ret_code, from_account, to_account, amount);
return ret_code;
}
Table table = openTable();
Entry entry0 = table.newEntry();
entry0.set("account", from_account);
entry0.set("asset_value", int256(from_asset_value - amount));
// 更新转账账户
int count = table.update(from_account, entry0, table.newCondition());
if(count != 1) {
ret_code = -5;
// 失败? 无权限或者其他错误?
emit TransferEvent(ret_code, from_account, to_account, amount);
return ret_code;
}
Entry entry1 = table.newEntry();
entry1.set("account", to_account);
entry1.set("asset_value", int256(to_asset_value + amount));
// 更新接收账户
table.update(to_account, entry1, table.newCondition());
emit TransferEvent(ret_code, from_account, to_account, amount);
return ret_code;
}
}
Table.sol
pragma solidity ^0.4.24;
contract TableFactory {
function openTable(string) public constant returns (Table); // open table
function createTable(string,string,string) public returns(int); // create table
}
// inquiry conditions
contract Condition {
//equal to
function EQ(string, int) public;
function EQ(string, string) public;
//unequal to
function NE(string, int) public;
function NE(string, string) public;
//greater than
function GT(string, int) public;
//greater than or equal to
function GE(string, int) public;
//smaller than
function LT(string, int) public;
//smaller than or equal to
function LE(string, int) public;
//limit the number of return record
function limit(int) public;
function limit(int, int) public;
}
// single entry data record
contract Entry {
function getInt(string) public constant returns(int);
function getAddress(string) public constant returns(address);
function getBytes64(string) public constant returns(byte[64]);
function getBytes32(string) public constant returns(bytes32);
function getString(string) public constant returns(string);
function set(string, int) public;
function set(string, string) public;
function set(string, address) public;
}
// data record set
contract Entries {
function get(int) public constant returns(Entry);
function size() public constant returns(int);
}
// Table main type
contract Table {
// select interface
function select(string, Condition) public constant returns(Entries);
// insert interface
function insert(string, Entry) public returns(int);
// update interface
function update(string, Entry, Condition) public returns(int);
// remove interface
function remove(string, Condition) public returns(int);
function newEntry() public constant returns(Entry);
function newCondition() public constant returns(Condition);
}
|-- webase-deploy # 一键部署目录
|--|-- log # 部署日志目录
|--|-- webase-web # 管理平台目录
|--|--|-- log # 管理平台日志目录
|--|-- webase-node-mgr # 节点管理服务目录
|--|--|-- log # 节点管理服务日志目录
|--|-- webase-sign # 签名服务目录
|--|--|-- log # 签名服务日志目录
|--|-- webase-front # 节点前置服务目录
|--|--|-- log # 节点前置服务日志目录
|--|-- nodes # 一件部署搭链节点目录
|--|--|-- 127.0.0.1
|--|--|--|-- node0 # 具体节点目录
|--|--|--|--|-- log # 节点日志目录
备注: 当前节点日志路径为一件部署搭链的路径,使用已有链请在相关路径查看日志