北京时间2018年6月30日,MOAC应用链正式上线公测。
北京时间2019年9月12日,MOAC发布Nuwa1.0.11,该版本适用于主网(mainnet)和测试网(testnet)。
本文为MOAC应用链安装及使用教程,在mainnet搭建应用链需要付出真金白银的moac哦。
1. 准备工作
从MOAC版本发布页下载系统软件包nuwa1.0.11.win.zip;
Windows版本适用于64位/32位Windows 7及以上系统。本文实际操作环境为:64位Windows 10 中文版。
2. 产生本地MOAC节点
解压系统软件包nuwa1.0.10.win.zip到本地硬盘。
安装节点到MOAC测试网。安装命令:
D:\nuwa1.0.10.win\win\vnode>moac --testnet \\把相应版本的执行程序改名为moac.exe,后同
注意:在moac测试网,任何情形使用moac命令启动节点均需要加--testnet。
节点自动安装到目录:C:\Users\[user]\AppData\Roaming\MoacNode\testnet
墨客测试网区块高度可以通过墨客测试网区块浏览器查询。
浏览器网址:http://47.75.144.55:3000/home。
特别注意:为了完成本篇文档的所有操作,需要用以下方式启动节点:
D:\nuwa1.0.10.win\win\vnode>moac --testnet --rpc --rpcaddr 0.0.0.0 --rpccorsdomain "*" --rpcapi="db,mc,net,chain3,personal,vnode,debug,scs"
使用该命令启动节点后,本编文档后面所用到的网页版钱包为:http://wallet.moac.io。
3.节点基本操作
此节内容参考本博客第三篇文档。
3.1 进入console界面
系统关机或主动关闭运行中的节点后,如果需要重新启动节点,在命令行中执行:
D:\nuwa1.0.10.win\win\vnode>moac –testnet --rpc
命令执行后,界面一直滚屏以同步区块数据。
3.2 进入attach界面
打开另一个命令(cmd)终端,转到当前目录,在命令行中执行:
D:\nuwa1.0.10.win\win\vnode>moac attach
该命令依赖于节点已经启动,命令执行后不会主动滚屏,而是等待命令。
3.3 创建账号
进入MOAC console界面后,执行命令:
> personal.newAccount()
系统会在以下目录:C:\Users\[userName]\AppData\Roaming\MoacNode\testnet\keystore,记录一个账号文件。
请保存好该文件,并牢记密码。
3.4 挖矿
在测试网,可以尝试挖矿,用于之后操作的gas费,进入moac attach界面后:
开始挖矿,执行命令:
> miner.start()
停止挖矿,执行命令:
> miner.stop()
查看挖矿状态,执行命令:
>mc.mining
查看余额变动,执行命令:
>loadScript("mctest.js")
>checkBalance()
4.部署Vnode矿池合约
此处内容参考中文wiki内容《代理vnode节点介绍》。
4.1 部署vnode矿池
从MOAC版本发布页下载合约VnodeProtocolBase.sol
部署时选择“Vnode Protocol Base”,填入参数Bmin(1),即最少押金为1。如图所示。
成功后得到合约地址,用于后面vnode的注册。
注意:该步骤非必须,可以直接加入测试网已经存在的公开的Vnode池子。
后面的步骤,可以直接使用公开的Vnode池子合约地址,里面已经注册的Vnode将会为你的子链提供服务。
4.2 添加节点到vnode矿池
添加本节点到vnode矿池的代码如下vnodeRegister.js,执行node即可。
var Chain3 = require('chain3');
var chain3 = new Chain3(new Chain3.providers.HttpProvider('http://localhost:8545'));
//vnode register
var baseAddr = "0x7610fd66c272332edd59a43460ad24eee1973bfe";
var basePasswd = "password";
var vnodeChain = "0x0fB05e4a2b878855e27A7675135BecA0E257e896";
var vnodeAddr = "7610fd66c272332edd59a43460ad24eee1973bfe";
chain3.personal.unlockAccount(baseAddr,basePasswd,0); //该步骤也可以在attach界面执行
sendtx(baseAddr, vnodeChain, '2','0x32434a2e000000000000000000000000' + vnodeAddr //数据1
+'0000000000000000000000000000000000000000000000000000000000000040'//数据2
+'0000000000000000000000000000000000000000000000000000000000000013'//数据3
//192.168.10.16:50062(填入本机实际IP地址值,并修改数据3和数据4)
+'3139322e3136382e31302e31363a353030363200000000000000000000000000');//数据4
function sendtx(src, tgtaddr, amount, strData) {
chain3.mc.sendTransaction(
{
from: src,
value:chain3.toSha(amount,'mc'),
to: tgtaddr,
gas: "9000000",
gasPrice: chain3.mc.gasPrice,
data: strData
});
console.log('sending from:' + src + ' to:' + tgtaddr + ' with data:' + strData);
}
主要参数如下:
添加成功后,启动节点方式不变。
该步骤也可以不使用代码,而是在http://wallet.moac.io的合约功能处完成,前提是你已经部署了自己的Vnode Proxy池子合约(也就是4.1节的步骤)。
其中:
注意:该步骤非必须,也就是说并不是必须把本节点注册为proxy Vnode,可以直接加入测试网已经存在的Vnode矿工池。仅在受网络限制,本节点不能同步的情况下,才必须自己部署Vnode矿池并将本节点注册为Vnode proxy。
5.scs注册
此处内容参考中文wiki内容《SCS矿工参与方法》。
5.1 部署子链矿池
部署子链矿池智能合约,用于子链SCS节点矿工加入矿工池。
从MOAC版本发布页下载合约SubChainProtocolBase.sol。进行合约部署。
此处内容参考本博客第四篇文档。
部署时选择“Sub Chain Protocol Base”,填入参数Protocol(POS)、Bmin(1)和protocol type(0表示pos,1表示ipfs),如图所示。
成功部署后
注意:该步骤非必须,可以直接加入测试网已经存在的矿工池。仅在受网络限制,本节点不能同步的情况下,才必须自己部署子链矿池。
5.2 启动SCS
在下载的节点文件中,有一个scs目录。目录下有一个配置文件userconfig.json。其中的Beneficiary为矿工收益账号。为了安全起见,建议采用与scsid不同的墨客底层账号用来获取子链的收益(scsid将会在后面讲到)。
进入目录scs\scsserver启动scs:
D:\nuwa1.0.10.win\win\scs>scsserver --verbosity 4
// or
D:\nuwa1.0.10.win\win\scs>scsserver -p "password" --verbosity 4
命令中:如果直接运行scsserver,则默认密码为 moacscsofflineaccountpwd,使用参数-p,则可以自己设定scs账号密码。
启动后,SCS将会在当前目录下生成一个keystore目录,并在目录中新建一个账号,这个账号就是scsid。如果想换一个scsid,则需要删除该目录中所有新内容,仅保留原来的2个文件,重新启动。
可以根据实际需要,按照以上步骤启动一个或多个scs。
5.3 注册SCS
在启动scs并已经知道一个子链矿池合约地址的情况下(见5.1节),可以进行注册。
写一个scsRegister.js,代码如下。
var Chain3 = require('chain3');
var chain3 = new Chain3(new Chain3.providers.HttpProvider('http://localhost:8545'));
//scs注册
console.log('SCS Register start!');
var baseAddr = "0x7610fd66c272332edd59a43460ad24eee1973bfe";
var basePasswd = "password";
var protocolAddr = "0x225Ebb0b9DF76E3D48eA0614943340611f635EA0";
var scsAddr = "755a37ec5ba302cd0022af2b8e3ff97c1996601b"; //不带0x开头
chain3.personal.unlockAccount(baseAddr, basePasswd,0);
sendtx(baseAddr, protocolAddr, '5','0x4420e486000000000000000000000000' + scsAddr);
function sendtx(src, tgtaddr, amount, strData) {
chain3.mc.sendTransaction(
{
from: src,
value:chain3.toSha(amount,'mc'),
to: tgtaddr,
gas: "9000000",
gasPrice: chain3.mc.gasPrice,
data: strData
});
console.log('sending from:' + src + ' to:' + tgtaddr + ' with data:' + strData);
}
主要参数如下:
特别注意:scsAddr的地址不要加上“0x”。
在文件目录下执行该注册文件scsRegister.js:
D:\nuwa1.0.10.win\win\scs>node scsRegister.js
在等待一定时间之后(通常是母链50个block),就进入子链矿池,成为该子链的候选SCS节点。注册后,保证金会从baseAddr账号转到子链矿池合约账号。
注册时缴纳的保证金,将在SCS被选中服务子链的时候临时扣除。下图为注册两个SCS,各交2个mc保证金的情况。
该步骤也可以不使用代码,而是在http://wallet.moac.io的合约功能处完成。
其中:
5.4 给SCS地址转账
scs在跟底层vnode通信或被调用时,tx是需要交易费的,因此需要在scsid存入1个mc作为gas费。
给scsid转账跟向普通账户转账一样。
5.5 查询SCS注册数量
如果是使用网页版钱包部署的子链矿池合约,可以直接在界面看到scs注册数量等信息。
或者,通过moac attach界面,使用合约地址查询注册scs数量
> mc.getStorageAt("0x225Ebb0b9DF76E3D48eA0614943340611f635EA0",0x02)
6.部署子链合约
此处内容参考中文wiki内容《DAPP用户的参与方法》。
6.1 编译子链合约
合约可以通过多种方式编译,比如在线编译工具remix等,如果是本地命令行编译,需要安装solidity环境。
D:\nuwa1.0.5.win\win> solcjs --optimize --bin --abi -o bin SubChainBase.sol SubChainProtocolBase.sol
SubChainBase.sol是子链合约,其中import "./SubChainProtocolBase.sol";
因此要把SubChainProtocolBase.sol合约放在同一个目录下。
编译结果如果没有error,会在bin目录生成相应的*.bin和*.abi文件。
6.2 部署子链合约
部署子链合约的代码如下deploySubChain.js,执行node即可。
var Chain3 = require('chain3');
var chain3 = new Chain3(new Chain3.providers.HttpProvider('http://localhost:8545'));
//deploy subChainBase
chain3.personal.unlockAccount(chain3.mc.accounts[0], 'password',0);
var proto = "0x225Ebb0b9DF76E3D48eA0614943340611f635EA0" ;
var vnodeProtocolBaseAddr = "0x0fB05e4a2b878855e27A7675135BecA0E257e896" ;
var min = 1 ;
var max = 10 ;
var thousandth = 1 ;
var flushRound = 20 ;
var subchainbaseContract = chain3.mc.contract([{"constant":true,......,"type":"event"}]);
var subchainbase = subchainbaseContract.new(
proto,
vnodeProtocolBaseAddr,
min,
max,
thousandth,
flushRound,
{
from: chain3.mc.accounts[0],
data: '0x6060604052600c601555670d...708e8ee3c23da8b02d0278eb0029',
gas: '9000000'
}, function (e, contract){
console.log(e, contract);
if (typeof contract.address !== 'undefined') {
console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);
}
})
子链控制合约subchainbase是DAPP用户使用子链的基本合约,其提供子链运行前和运行中的一些必要接口。
通常来说,子链控制合约subchainbase需要修改相应的内容如下:
6.3 子链控制合约信息
部署成功后:
得到子链控制合约地址和本次交易hash。
该合约不是在网页版钱包部署的,因此不会在界面上显示,此时需要将该合约加到界面上。
点击“WATCH MOTHERCHAIN CONTRACT”按钮。
输入刚部署的合约的合约地址和JSON(就是合约的abiString),自己给合约取个名称,点击“好”,会在界面上增加该合约。之后对合约的操作跟使用网页版钱包部署成功的合约一致。
6.4 子链开放注册
通过开放子链注册,候选SCS内部完成注册,最终成为子链的一员,才有资格参与子链的相关业务。 需要注意的是:SCS参与子链注册是通过SCS地址(我们也称为scsid,放在“./scskeystore”目录下)发送交易到子链完成;因此需要给SCS地址储备一定量的moac,建议1个moac。同时子链合约需要最终提供gas费给scs,因此,也需要给子链控制合约发送一定量的moac。
请注意:给子链控制合约发送moac,不能直接send,需要用合约里的函数addFund()。
部署子链开放注册的代码如下registerOpen.js,执行node即可。
var Chain3 = require('chain3');
var chain3 = new Chain3(new Chain3.providers.HttpProvider('http://localhost:8545'));
//register open
var dappAddr = "0x7610fd66c272332edd59a43460ad24eee1973bfe";
var dappPasswd = "password";
var subchainAddr = "0x8a194e9567d7339b968dac61546a52f89a8c7a2f";//子链控制合约地址
chain3.personal.unlockAccount(dappAddr, dappPasswd,0);
sendtx(dappAddr, subchainAddr, '0','0x5defc56c' );
function sendtx(src, tgtaddr, amount, strData) {
chain3.mc.sendTransaction(
{
from: src,
value:chain3.toSha(amount,'mc'),
to: tgtaddr,
gas: "2000000",
gasPrice: chain3.mc.gasPrice,
data: strData
});
console.log('sending from:' + src + ' to:' + tgtaddr + ' with data:' + strData);
}
该步骤也可以不使用代码,而是在http://wallet.moac.io的合约功能处完成。
6.5 查看注册情况
通过registerOpen后,系统将自动选择符合条件的SCS节点并通知他们进行注册,DAPP用户需要通过如下方法查看已经注册完成的SCS节点数目(nodeCount):
>mc.getStorageAt(subchainAddr,0x0e)
通过合约地址subchainAddr查询合约中第0x0e个public成员变量(即nodeCount)的值,请不要修改此值 当达到子链运行需要的SCS的数量区间后,即可进入RegisterClose步骤。
该步骤也可以在http://wallet.moac.io的合约功能处直接查看。还可以查询已经注册的scs的id。
6.6 子链关闭注册
首先介绍一下RegisterClose的主要工作:
关闭子链注册后,候选SCS不能再通过subchain RegisterOpen方式注册该子链,已经注册的SCS处于正常运行状态,参与子链的相关业务,如:处理交易、出块、刷新等。
部署子链关闭注册的代码如下registerClose.js,执行node即可。
var Chain3 = require('chain3');
var chain3 = new Chain3(new Chain3.providers.HttpProvider('http://localhost:8545'));
//register open
var dappAddr = "0x7610fd66c272332edd59a43460ad24eee1973bfe";
var dappPasswd = "password";
var subchainAddr = "0x8a194e9567d7339b968dac61546a52f89a8c7a2f";//子链控制合约地址
chain3.personal.unlockAccount(dappAddr, dappPasswd,0);
sendtx(dappAddr, subchainAddr, '0','0x69f3576f' );
function sendtx(src, tgtaddr, amount, strData) {
chain3.mc.sendTransaction(
{
from: src,
value:chain3.toSha(amount,'mc'),
to: tgtaddr,
gas: "2000000",
gasPrice: chain3.mc.gasPrice,
data: strData
});
console.log('sending from:' + src + ' to:' + tgtaddr + ' with data:' + strData);
}
其中,
执行完毕,如果一切正常,子链建成并开始出块。
该步骤也可以不使用代码,而是在http://wallet.moac.io的合约功能处完成。
实测环境中3个scs轮流出块,显示如下。
图中显示本scs出块正常,当前为子链第15个区块,由本scs挖矿出块成功。
如果是同步其他scs出的子链区块,“SendBkToVnode”显示为“Insert”,也就是同步其他scs的区块。
至此,子链部署完成。
7.SCS monitor
Monitor是一个特殊的SCS节点,它是一种模式,DAPP用户可以通过这个节点来监控自己的子链运行状态和业务数据。
SCS Monitor不参与子链共识,因此只能查看,不能修改数据。即使子链已经运行,Monitor也能注册加入。
Monitor SCS启动方式为( 需要自设密码,加上-p "password"):
D:\nuwa1.0.10.win\win\scs>scsserver --rpc --rpcaddr 0.0.0.0 --rpcport 2345 --rpccorsdomain "*" --verbosity 4
启动后,DAPP用户通过调用子链控制合约subchainbase中的registerAsMonitor方法使Monitor SCS接入子链同步数据。
部署子链开放注册的代码如下registerAsMonitor.js,执行node即可。
var Chain3 = require('chain3');
var chain3 = new Chain3(new Chain3.providers.HttpProvider('http://localhost:8545'));
//register as monitor
var dappAddr = "0x7610fd66c272332edd59a43460ad24eee1973bfe";
var dappPasswd = "password";
var subchainAddr = "0x4132d3d98e5781507633dfd2248d810ab05d1431";//子链控制合约地址
var scsAddr = "d35eb82143aa45857bb5324a3b5b493d4078e812"; //monitor的scsid,不带0x开头
subchainRegisterAsMonitor (dappAddr,dappPasswd,subchainAddr,'1',scsAddr);
function subchainRegisterAsMonitor (dappAddr,dappPasswd,subchainAddr,amount,scsAddr)
{
chain3.mc.sendTransaction(
{
from: dappAddr,
value:chain3.toSha(amount,'mc'),
to: subchainAddr,
gas: "2000000",
gasPrice: chain3.mc.gasPrice,
data: '0x4e592e2f000000000000000000000000' + scsAddr
});
console.log('sending from:' + dappAddr + ' to:' + subchainAddr + ' with data:' + '0x4e592e2f000000000000000000000000' + scsAddr);
}
部署成功后可以看到,SCS monitor开始同步子链区块。
该步骤也可以不使用代码,而是在http://wallet.moac.io的合约功能处完成。
8.在子链部署业务逻辑合约
8.1 使用钱包工具部署业务逻辑合约
登录http://wallet.moac.io,点击“部署新合约”。
本文档使用一个简单的合约,mySubContract.sol,代码如下:
pragma solidity ^0.4.18;
contract Calc{
uint public count;
uint public equation;
function add(uint a, uint b){
count++;
equation = a + b;
}
function getCount() constant returns (uint){
return count;
}
function getEquation() constant returns (uint){
return equation;
}
}
部署子链业务逻辑合约时,勾选复选框“MicroChain Dapp”;
然后填写合约的内容,按步骤即可成功部署子链业务逻辑合约。同时在contract页面的MICROCHAIN CONTRACTS显示。
点击进去,会发现显示的合约地址仍然是子链控制合约地址,同时显示scs monitor的address和port;
右边的合约函数就是业务逻辑合约的函数。
请注意,此时Nonce值应该自动是1,才是正确状态,如果等待很久之后还是0或者-1,则表示没有部署成功。
部署不成功的原因很多,比如本地网路问题,或者scs出块时子链分叉等。
正常后,可以对子链业务逻辑合约进行操作,每次操作成功后,Nonce会自动增加1。
本例中,左边可以直接看到测试运算结果。
在对子链业务逻辑合约的操作中,可以在scs monitor界面看到交易的发送情况,基本格式如下:
====== Transactions: 1 =====
TX(f3eb6baf45ff003f766d88bf7dddd6894ec4bf72ebdae1a2931241674ad7f8d4)
Contract: false
From: 7610fd66c272332edd59a43460ad24eee1973bfe
To: 6b4e01e1598fdabd7c926260ae614005bf1cc9a0
Nonce: 1
GasPrice: 0x4a817c800
GasLimit 0x0
Value: 0x0
Data: 0x771602f700000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000005
V: 0xee
R: 0xf0023109bd51efc72702637bf4ef3c7ca11df228bf258d1b31ed593c2e9f9686
S: 0x6bdd7642aa10d94e837ee9ae5c39ee25be395182355cab554a6ec4b67534fe28
Hex: f8bf01808504a817c80080946b4e01e1598fdabd7c926260ae614005bf1cc9a080b844771602f70000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000501947610fd66c272332edd59a43460ad24eee1973bfe81eea0f0023109bd51efc72702637bf4ef3c7ca11df228bf258d1b31ed593c2e9f9686a06bdd7642aa10d94e837ee9ae5c39ee25be395182355cab554a6ec4b67534fe28
SysCnt: 0
ShardingFlag: 1
Via: [118 16 253 102 194 114 51 46 221 89 164 52 96 173 36 238 225 151 59 254]
=============================
8.2 使用代码部署业务逻辑合约
在已经出块的子链上部署业务逻辑合约的代码如下deployContractOnSubchain.js,执行node即可。
const Chain3 = require('chain3');
const vnodeUri = 'http://localhost:8545';
let chain3 = new Chain3();
chain3.setProvider(new chain3.providers.HttpProvider(vnodeUri));
if(!chain3.isConnected()){
throw new Error('unable to connect to moac vnode at ' + vnodeUri);
}else{
var subchainbaseaddress = "0xb104eE51270e930D889CbBA2d0A578Dc3e82279f"; //subchainBase合约地址
var dataStr = "0x6060604052341561000f57600080fd5b33600160006101000a81548173......0029";//子链业务逻辑合约Bin,加0x
chain3.mc.sendTransaction(
{
from: chain3.mc.coinbase,
value:chain3.toSha('0','mc'),
to: subchainbaseaddress,
gas: 0,
shardingFlag: "0x1",
data: dataStr,
nonce: 0,
via: chain3.mc.coinbase,
});
}
9.增加新的出块scs
一个子链已经出块,想加入新的出块scs,方法是:
48027:Got Upload Block reply from proxy server: len:8
48027:Uploading block 30524 to the Proxy server...
10.子链浏览器
上面的步骤都完成,子链已经出块,scs monitor部署完成并正常工作,可以到浏览器查询子链区块信息。
点击“MicroChain Form”,界面上写入相应参数:
参数主要包括SCS monitor的ip地址和端口,子链合约地址等。点击Submit按钮。
可以看到子链的基本信息、区块信息及构建该子链的SCS。