go-stormchain is a blockchain technology that implements a multichain ecosystem by supporting multiple blockchains including public, private and federated chains. It also supports multiple consensuses.
由全球区块链技术爱好者组成,共同开发和管理的,支持多种共识的多链架构区块链技术。信息公开,技术开源,可以为应用提供专属区块链,支持高TPS。自带区块链存储功能,使用方便。本技术还在持续开发中。
由**工程师自主研发基于PBFT共识的区块链技术,支持国家监督和管控,多节点备份,数据存证不可篡改。以国密局标准算法加密原始数据,提取文件Hash上链传输,保护原文件及用户信息安全。
下载运行程序 storm (选择正确的操作系统)
Download the latest executables for your operating system from releases.
- Mac OS: storm-os
- Linux: storm-linux
将 storm 复制到需要安装的节点服务器上。在这个指南中,我们将使用三台装有 Ubuntu 操作系统的服务器。(Storm区块链至少需要两个节点才能运行。)在服务器上,可以建立新文件夹 storm_node 作为节点运行根目录。将执行文件 storm 存到这个目录下。(如果要在同一个服务器上跑多个节点,可以生成多个文件夹如 storm_node1, storm_node2,然后执行下面的步骤。)
在区块链上,账号是用户身份的代表。每个节点程序都必须通过一个账号来运行。这个账号文件必须存在节点服务器上,密码由指定管理员保管。所以第一步,我们在三台服务器上各建一个账号。
$ cd storm_node
$ ./storm --datadir data account new
INFO [02-06|14:13:49.711] Maximum peer count FST=50 LES=0 total=50
Your new account is locked with a password. Please give a password. Do not forget this password.
Password:
Repeat password:
Your new key was generated
Public address of the key: 0x084149366635cD8E727d1eD50c363107b1b2a565
0x084149366635cD8E727d1eD50c363107b1b2a565
是账号的公钥,可以公开。
使用 --datadir data
的目的是把账号建立在节点运行根目录下的 data 文件夹中,便于查找和管理。运行完后,将会看到 data 中有一个新的名为 keystore 的文件夹。钥匙文件就在这个文件夹内。
我们可以将密码写到一个密码文件中,方便节点启动。这个文件在节点启动后需要手动删除。
$ echo 'password' > password.txt
在其他两个节点上也做同样的操作,并将密码保管好。三个公钥收集起来,等下需要使用。
利用stormchain技术,FileStorm与MOAC共同打造了一条应用链。可以通过在MOAC主网上发布一个智能合约生成创世文件。具体介绍可以看这里。
可以在一台出块节点上用这样的方式来初始节点并生成创世文件。
./storm --datadir data \
--blockSec 7 \
--totalSupply 20000 \
--flushEpoch 360 \
--initValidators "14723A09ACff6D2A60DcdF7aA4AFf308FDDC160C,4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB" \
init
-
datadir 本地数据路径
-
blockSec 出块速度(单位:秒)
-
totalSupply 发行通证总数(不用加0,没有就不发行)
-
flushEpoch 刷新周期。
-
initValidators 创世验证人列表,逗号分开。
这时,同目录下会生成一个这样的文件: 1583305010522115000.json。这就是你的创世文件
修改完以后将文件保存好。然后复制到其他两个节点上。一条区块链上的所有节点的创世文件必须一模一样。所以,以后需要建新节点,就到这三个节点这里拿创世文件。
在其他两台节点服务器上运行下面的指令。节点初始化就完成了。区块链的数据库内容就被存到了 data 中。
$ ./storm --datadir data init 1583305010522115000.json
节点初始化成功你会看到这样一条信息
INFO [02-08|12:50:17.448] Successfully wrote genesis state database=lightchaindata hash=33b98a…e3f240
$ ./storm --datadir data --networkid 20090103 --gasprice '0' --syncmode 'full' --port 30317 --unlock '0x084149366635cD8E727d1eD50c363107b1b2a565' --password password.txt --mine
-
--datadir data 是指定区块数据保存在当前目录下的 data 目录中。
-
--networkid 20090103 这个networkid必须和创世文件中的chainId相同。
-
--gasprice '0' 这是设置交易费。无通证的联盟链要把交易费用设为0。若是有通证区块链可以不填,用创世区块中的gasLimit。
-
--syncmode 'full' 是指同步方式为全同步。创始节点必须用全同步方式启动。后面加入的节点可以不写,或者采用其他同步发方式。
-
--port 30317 这是 Storm 区块链的通讯端口。缺省值为30303。这是一个可选项,如果在一台服务器上跑多个节点,就必须修改这个值。
-
--unlock '0x084149366635cD8E727d1eD50c363107b1b2a565' 这里的数字记得要改成前面为这台服务器生成的管理员账号。解锁后,这个节点就可以出块。
-
--password password.txt 使用存在密码文件中的密码。
-
--mine 启动挖矿(验证出块)
运行成功后,打开一个新窗口,将密码文件删除。
$ rm password.txt
这时候,我们会看到所有节点都停在第二个块
INFO [02-06|13:01:02.505] Commit new mining work block=1 sealhash=56a809…a06463 uncles=0 txs=0 gas=0 fees=0 elapsed=158.258µs
INFO [02-06|13:01:02.634] Sealed a new block block=1 sealhash=56a809…a06463 hash=17d48d…cb74e4 elapsed=128.207ms
INFO [02-06|13:01:02.634] Mined a potential block block=1 hash=17d48d…cb74e4
INFO [02-06|13:01:02.635] Commit new mining work block=2 sealhash=72548f…ba20b0 uncles=0 txs=0 gas=0 fees=0 elapsed=809.66µs
INFO [02-06|13:01:02.635]
这是因为三个节点还没有互相连上,所以,下一步,就是要做节点的连接。
选择一个节点做为连接主节点,在服务器上新开一个窗口,做如下操作,就可以进入节点控制面板。
$ cd storm_node
$ ./storm attach data/storm.ipc
然后在面板中做如下操作,就可以得到节点的网络ID
> admin.nodeInfo.enode
"enode://0e3a9317c4c9e8910e5d34f627ab798ac0814ac732cb433db4d73382a39c1cb2e8fd35fc53ad406f5883f86a45bc9fb083503ed357ed1a07b5c0a078815c534f@[::]:30317"
在另一个节点上打开节点控制面板
$ cd storm_node
$ ./storm attach data/storm.ipc
然后做如下操作,就可以将两个节点相连
> admin.addPeer("enode://0e3a9317c4c9e8910e5d34f627ab798ac0814ac732cb433db4d73382a39c1cb2e8fd35fc53ad406f5883f86a45bc9fb083503ed357ed1a07b5c0a078815c534f@[::]:30317")
记得在[::]填入正确的节点IP。如果是内网必须使用内网IP。
在第三个节点上也做同样操作,就可以将三个节点连起来。然后三个节点就开始轮流出块。
启动节点
$ ./storm --datadir data --networkid 20090103 --syncmode 'full' --port 30329
networkid和port可能根据实际情况修改。
在另一个窗口上打开节点控制面板
$ cd storm_node
$ ./storm attach data/storm.ipc
然后连接主节点,从而与整个网络相连
> admin.addPeer("enode://0e3a9317c4c9e8910e5d34f627ab798ac0814ac732cb433db4d73382a39c1cb2e8fd35fc53ad406f5883f86a45bc9fb083503ed357ed1a07b5c0a078815c534f@[::]:30317")
这时候,新节点还不能验证出块,只能接受区块信息,也就是同步节点。
如果需要在stormchain上做开发,建议使用同步节点。如何在stormchain上做开发,可以查看wiki。
如果同步节点想要成为出块节点,就必须遵守所用共识机制。本指南采用的是pbft共识,增加新节点,必须通过验证节点投票,得到超过50%的赞同票就可以成为验证节点。下面,我们就来看看验证节点的投票功能。
联盟链上的每一验证节点都可以代表一个独立的利益体。增加和减少验证节点都需要超过半数的验证节点投票决定。验证节点有一组投票功能,可以在控制面板中输入 pbft 来查看
> pbft
{
votes: {},
blockStatus: function(),
dropVote: function(),
getBlockStatusByHash: function(),
getBlockStatusByNumber: function(),
getValidatorsByHash: function(),
getValidatorsByNumber: function(),
vote: function()
}
vote: 给一个新节点投赞成或者反对票。
dropVote: 撤销给一个节点的投票。
votes: 显示节点所有的投票。
blockStatus: 显示区块状态,包括出块节点信息。
getBlockStatusByHash: 通过区块哈希查找区块状态。
getBlockStatusByNumber: 通过区块数查找区块状态。
getValidatorsByHash: 通过区块哈希查找验证人信息。
getValidatorsByNumber: 通过区块数查找验证人信息。
给一个节点投赞成票的指令是
> pbft.vote('0x53e5c08cb895599e7cfa5da58a783a56e9f140db', true)
投反对票是
> pbft.vote('0x53e5c08cb895599e7cfa5da58a783a56e9f140db', false)
投完票后可以撤销
> pbft.dropVote('0x53e5c08cb895599e7cfa5da58a783a56e9f140db')
如果在投票生效前撤销,相当于弃权,且不能再投票。如果投票已生效,撤销将没有意义。
查看在某个区块,如第300个块时的验证人列表,可以使用
> pbft.getValidatorsByNumber(300)
如果联盟成员达成共识,决定同时创建一条新链,可以通过第一到第六步生成节点创建新链。但是一旦链建成后,就必须用投票的方式增加新的验证节点。确保区块链的安全性。
前面介绍的方法是通过服务器终端界面操作启动节点。终端界面关闭或者掉线,节点程序就会停止。所以,我们要让节点程序在服务器后台操作。命令如下
$ nohup ./storm --datadir data --networkid 20090103 --syncmode 'full' --port 30317 --unlock '0x084149366635cD8E727d1eD50c363107b1b2a565' --password password.txt --mine > storm.out 2>&1 &
这样,我们就把程序在后台跑起来,并且把日志输入到一个叫 storm.out 的文件中去了。可以通过下面的指令来看日志
$ tail -100f storm.out
如果要中止程序,可以通过下面指令
$ ps -ef | grep storm
找到正在运行的 storm 进程,记住第二个数字(在这里是78115)
501 78115 78036 0 1:37PM ttys014 0:00.06 ./storm --datadir data --networkid 20090109 --gasprice 0 --syncmode full --port 30343 --unlock 0xfe8c8e5Cf019f0DAF4d16f14eC88d5971b16cdD2 --password password.txt --mine
然后执行
kill -9 78115
这样节点就停止了。
节点升级,只需要中止节点程序,替换节点程序,然后重新启动即可。如果同时管理几个节点,建议一次升级一个节点。等节点出块后再更新其他节点。节点重新启动可能需要最长10分钟来连接回区块链网络,如果想快速连回,可使用第六步中 admin.addPeer 的方式快速建立连接。
INFO [03-01|14:09:57.005] Commit new mining work block=8944 sealhash=d0f9c1…0999be uncles=0 txs=0 gas=0 fees=0 elapsed=799.162µs
INFO [03-01|14:10:02.002] Imported new blocks block=8944 hash=f193f4…8d0170 blks=1 txs=0 mgas=0.000 dirty=0.00B
INFO [03-01|14:10:02.002] Commit new mining work block=8945 sealhash=05508e…d47330 uncles=0 txs=0 gas=0 fees=0 elapsed=232.068µs
INFO [03-01|14:10:07.002] Imported new blocks block=8945 hash=ca9823…981c56 blks=1 txs=0 mgas=0.000 dirty=0.00B
INFO [03-01|14:10:07.002] Commit new mining work block=8946 sealhash=490317…94c810 uncles=0 txs=0 gas=0 fees=0 elapsed=235.869µs
INFO [03-01|14:10:12.005] Sealed a new block block=8946 sealhash=490317…94c810 hash=daff82…69ecd7 elapsed=5.002s
INFO [03-01|14:10:12.005] Mined a potential block block=8946 hash=daff82…69ecd7
INFO [03-01|14:10:12.006] Commit new mining work block=8947 sealhash=8a7231…20c7bd uncles=0 txs=0 gas=0 fees=0 elapsed=888.573µs
INFO [03-01|14:10:12.006] Waiting for mining work.
INFO [03-01|14:10:02.002] Reached canonical chain block=8937 hash=9c2b14…75ef51
INFO [03-01|15:10:02.012] Throw away a block block=8947 hash=8a7231…20c7bd
这是一个出块节点上常见的日志,我们来解释一下。
- Commit new mining work - 把本地交易进行打包生成一个本地区块。
- Imported new blocks - 把通过共识选择的别的节点生成的新区块导入。
- Sealed a new block - 被共识选中成为下一个出块节点,把本地区块封装。
- Mined a potential block - 把自己封装的本地区块导入。
- Waiting for mining work - 出块节点要等待一段时间才能继续出块。
- Reached canonical chain - 本节点前些时候出的一个区块终极确认不可再改。(一般等6个区块)
- Throw away a block - 本节点前些时候出的一个区块无效被别的节点替代(常见于网络不畅时收到出块节点太慢)
其他参数
- block 区块高度
- hash 区块哈希
- sealhash 打包哈希值。PBFT每组投票都需要一个ID,sealhash就可以理解成投票ID。
- blks 区块数量。(导入区块的时候,如果网络不通畅,有时候会导入多个ID。)
- txs 区块里的交易数量
- gas 燃料费用
- fee 总费用
- elapsed 生成区块的时间
- mgas 燃料费用(单位 gwei)
- dirty 是否超时
- uncles 叔块。网络延时很大的情况下会出现叔块。
同步节点上常常会看到这样的日志
INFO [03-01|14:42:34.539] Imported new blocks block=194366 hash=9f4c6d…e6d34e blks=1 txs=0 mgas=0.000 dirty=0.00B
INFO [03-01|14:42:58.498] Imported new blocks block=194367 hash=c6be54…7580be blks=1 txs=0 mgas=0.000 dirty=0.00B
INFO [03-01|14:43:06.749] Synchronisation slowing down peer=99c0270b228226d2 msg="retrieved hash chain is invalid"
INFO [03-01|14:43:09.538] Imported new blocks block=194371 hash=aaae9b…2d1dbc blks=1 txs=0 mgas=0.000 dirty=0.00B
INFO [03-01|14:43:27.821] Reimported chain segment block=104371 elapsed=109.200ms blks=7 hash=421faa…b31354
INFO [03-01|14:43:33.864] Imported new blocks block=194372 hash=1fbe72…7420de blks=1 txs=0 mgas=0.000 dirty=0.00B
INFO [03-01|14:43:41.231] Synchronisation slowing down peer=99c0270b228226d2 msg="retrieved hash chain is invalid"
INFO [03-01|14:43:44.539] Imported new blocks block=194376 hash=eec99b…381eb0 blks=1 txs=0 mgas=0.000 dirty=0.00B
INFO [03-01|14:44:17.783] Imported new blocks block=194377 hash=fe3c77…f280fd blks=1 txs=0 mgas=0.000 dirty=0.00B
- Imported new blocks 正常导入区块
- Synchronisation slowing down 同步节点网络不畅就会出现这个信息。
- Reimported chain segment 如果前面导入区块有漏掉的,就会从漏掉的区块一直往前一直拿到当前块。