本文档承接上篇文档。
FileStorm是在墨客子链上实现的基于IPFS的去中心化存储平台。这个平台的用户有三类。
- 存储提供方: 存储提供方将会提供用于存储的硬件设备,如带大容量硬盘的电脑,或者订制的硬件盒子。设备需要安装FileStorm程序,用来链接墨客FileStorm子链,和IPFS网络。为FileStorm提供存储可以得到收益,就是俗称的存储挖矿。
- 应用部署方:应用部署方为FileStorm子链的创建者。他们可以搭建一个专门的子链为自己的应用做存储。应用部署方需要承担运营FileStorm子链的费用(墨客也会做为应用部署方部署一条FileStorm子链供用户使用。)
- 存储使用者:存储的使用者通过使用应用部署方部署的应用来存储和读取文件。存储使用者无需为使用FileStorm付费。但是可能要承担使用应用的费用。
1.部署子链逻辑合约
1.1 下载合约
到官方公布的网站https://github.com/MOACChain/FileStorm/releases下载合约FileStormMicroChain.sol。
1.2 部署该合约到已经正常出块的子链
部署子链业务逻辑合约时,勾选复选框“MicroChain Dapp”;
- MicroChain Base Address:在里面填上子链控制合约的地址;
- SCS Monitor Address:填写SCS Monitor的IP地址(本机可以用127.0.0.1);
- SCS Monitor Port:SCS Monitor启动端口。
在“选择合约”选中“File Storm Micro Chain”,点击"部署合约"。
1.3 部署完成后会显示子链合约
点击进去后,发现合约地址还是子链控制合约地址。
- 左上角显示子链区块的高度,实例为862,且一直同步变化;
- 合约信息会显示SCS monitor的地址和端口;
- 函数会选择子链业务逻辑的功能。
2.把文件存入fileStorm
2.1 在本地新建一个ipfs节点
注意区分fileStorm的存储提供方和使用者的不同:前面的ipfs节点都运行在存储提供方的设备scs上,此处的节点是存储使用者为了方便操作建立的。本文把所有操作在同一台主机进行,也就是说做了存储提供方、部署方和使用者的所有工作。
步骤跟上一篇建立ipfs节点一样:
- 修改环境变量IPFS_PATH的值为C:\Users\1\.ipfs6;
- 到目录下运行:ipfs init;
- 接着运行:ipfs daemon。
2.2 将文件写入新建的ipfs节点
新建一个测试文件,比如test.txt;并在里面写入内容。
到ipfs目录下,执行命令:
C:\go-ipfs_v0.4.15_windows-amd64\go-ipfs>ipfs add test.txt
成功执行,返回结果如下:
里面包含一个hash值,就是所传测试文件test.txt的hash。
2.3 将文件写入fileStorm
到子链合约部署的地方,使用write函数将文件写入。
此处每成功对合约操作一次,Nonce会自增1。
如果顺利执行,会在monkey界面有相应动作,并且子链的三个scs均会保存文件test.txt。
2.4 命令行读取写入的文件
进入ipfs1目录(将前文中的环境变量IPFS_PATH值设置为“C:\Users\1\.ipfs1”);
启动一个新的cmd,使用以下命令查看文件写入情况:
C:\MyWorkSpace\go-ipfs>ipfs pin ls
显示有一个新的文件hash被写进来:请注意,该文件的hash跟写入时的hash值不一样。
使用以下命令读取文件内容:
C:\MyWorkSpace\go-ipfs>ipfs cat [hash]
结果显示如下:请注意,该文件的内容跟写入时的文件相比,多了一些字符,这也是上图中显示不同hash值的原因。
2.5 从fileStorm读取文件
到子链合约部署的地方,使用read函数读取文件。
执行后回到ipfs,会显示有一个新的文件hash被写进来:请注意,该文件的hash跟写入test.txt时的hash值一致。
此时去读取文件内容,得到的内容跟最初写入的文件test.txt一致。
3.代码操作fileStorm
在2.2节,待保存到fileStorm的文件在执行ipfs add命令之后会加入到本地ipfs并返回一个hash值。
3.1 将文件hash转换为十六进制代码
使用npm命令安装ethereumjs-bin功能模块:
D:\nodeJS_Project>npm install --g ethereumjs-abi
使用如下代码将文件hash转换为十六进制代码,保存为文件toHex.js,直接node即可。
var abi = require('ethereumjs-abi');
var original = 'QmQNe96LqV5TcRQyBz12iQXPZQjemBqkgnpHki3wmKjtd6';
var encoded = abi.simpleEncode('write(string)', original);
console.log('original', original);
console.log('encoded', encoded.toString('hex'));
下图为2个不同文件hash的实际运行结果:
3.2 写(write)文件
以下代码用于写文件。
// write(fileHash)
chain3.mc.sendTransaction(
{
from: chain3.mc.accounts[0],
value:chain3.toSha('0','mc'),
to: subchainbaseaddress,
gas: "200000",
gasPrice: chain3.mc.gasPrice,
shardingflag: 1,
data: '0xebaac771000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000002e'
nonce: 1,
via: chain3.mc.accounts[0]
});
- from: 必须是本机keystore里存在的一个账号。如果是vnode里第一次生成的就是chain3.mc.accounts[0],必须先进行一下personal.unlockAccount(mc.accounts[0])解锁使用;
- to: subchainbaseaddress是SubChainBase合约地址,必须由应用项目方提供,此处用前面测试得到的地址;
- data: 把第3.1节得到的数字(文件hash值的hex)加到data的数值里2e的后面;此处注意:3.1节得到的hex实际包含了write前置数据,因此仅需要将结果里面的2e后面的128位加到上面代码的后面。在后面的read和remove中,前置的数据不同,还是将hex结果的2e的后面128位加到代码数据的后面。
- nonce:每次调用要把nonce手动加1;
- via:必须跟vnode文件夹下的vnodeproxy.json文件里的配置一致。
调用结果:IPFS文件被存到FileStorm子链的每一个节点上,文件Hash值被改变。
3.3 读(read)文件
以下代码用于读文件。
// read(fileHash)
chain3.mc.sendTransaction(
{
from: mc.accounts[0],
value:chain3.toSha('0','mc'),
to: subchainbaseaddress,
gas: "200000",
gasPrice: chain3.mc.gasPrice,
shardingflag: 1,
data: '0x616ffe83000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000002e'
nonce: 2,
via: mc.accounts[0]
});
调用结果:FileStorm子链的每一个节点上都会出现原始Hash值的原文件。(会在24小时后自动删除)。
3.4 删除(remove)文件
以下代码用于删除文件。
// remove(fileHash)
chain3.mc.sendTransaction(
{
from: mc.accounts[0],
value:chain3.toSha('0','mc'),
to: subchainbaseaddress,
gas: "200000",
gasPrice: chain3.mc.gasPrice,
shardingflag: 1,
data: '0x80599e4b000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000002e'
nonce: 3,
via: mc.accounts[0]
});
调用结果:IPFS文件会从FileStorm子链的每一个节点上被删除。