200行代码实现一个可追溯的文件系统

发布时间:2019-11-08          作者:超哥


    
难篡改、可追溯,这两个性质是区块链被广泛认可的良好特性。
最早比特币只实现了交易转账的可追溯,如果要实现数据变更的可追溯,就需要编写智能合约来实现了,可惜大多数区块链系统的合约开发都不是很好用,这个门槛把很多试图体验区块链的人挡在了门外。
如果能把区块链变成一块硬盘,放在里面的文件自动就具备了“难篡改、可追溯”的性质,是不是很酷?本文将介绍如何基于百度超级链来来实现这样一个文件系统,主要的代码只有200行左右。

 

传统的文件系统是操作系统的一部分,一般是在内核里面实现的。区块链系统都运行在用户态,如何把区块链变成一块存储盘呢?这就要用到Fuse(Filesystem in Userspace)了,简单来说它是一个用户态文件系统框架,只要你的程序实现了open、read、write等等一系列接口,就可以虚拟出一个文件系统。
                                                  
 图1 Fuse的原理(引自Wikipedia)
在超级链中,可以通过智能合约的put_object把数据存储到区块链上,通过get_object查询,也可以通过new_iterator遍历查询。
设计思路
一个简单而大胆的想法,就是用文件的名字作为key,然后把文件的内容作为value,借助智能合约存储到���块链上,比如put_object(“/mydir/1.txt”, “a long story”)。读取该文件,就是调用get_object(“/mydir/1.txt”)。列出目录,就是通过new_iterator(“/mydir”)循环遍历迭代器,拿到所有该前缀的文件名。说干就干,马上写出一个超级链合约,实现我们这个文件系统的内核。
   图2 智能合约实现get,put,scan三个接口,用于模拟文件系统
各位看官可能会问,这个合约的功能和redis、leveldb等key-value存储相比,有什么特殊之处呢?这个就要说到超级链的XuperModel模型了。在超级链里面的事务模型是XuperModel,它是基于经典的UTXO模型演化而来,经典的UTXO模型只能描述转账场景,而XuperModel创新之处在于可以描述更加通用的数据变更。
   图3 智能合约存储的多版本管理
超级链底层的数据多版本机制实现也与数据库不同。数据库的一般做法是将逻辑Key+版本号拼接成物理Key,但是这个方式只能保留有限个版本,一旦版本太多,就会导致区间查询迭代很慢,因为要Scan大量无用的老版本。超级链用了一种链式哈希的多版本接口,在状态树中Key对应的Value只是哈希指针,指向账本中事务的Output字段,要回溯之前的老版本也只需要通过事务的Input指针再往前回溯。当需要回滚事务或区块的时候,产生的IO开销也极低。
接下来,要实现一个模块,这个模块起到“桥梁”的作用,把区块链智能合约存储映射成一块盘,这个就是用到了文章开头提到的Fuse。 
图4. 把合约空间mount为一块盘
简单起见,我们用python来实现,python有个库python-fuse可以帮助我们少写很多代码。下图贴出了主要的代码逻辑,目前的实现没有做chunk管理,一个文件就是一个整体。对于随机读、随机写的实现比较简单粗暴。
                                                 
  图5.  Xfs的主要代码逻辑

 

见证奇迹的时刻,运行XFS
让我们看看效果。首先启动xchain单机节点。
nohup ./xchain &          //启动grpc服务
nohup ./xchain-httpgw &   //启动http服务
然后, 创建一个空目录:mkdir –p /tmp/myxfs
部署合约,python3.6 deploy_fs.py
最后, 启动xfs 把合约mount到/tmp/myxfs:python3.6 xfs_demo.py -f /tmp/myxfs/
图6. 用起来本地文件系统体验一致,丝般顺滑
同时,在xfs_demo的控制台上,看到了如下输出,这个是系统调用触发的,我们可以看到一次写入操作产生了区块链上的一个交易,有交易id: 303c867e195ba464778250b2e7f21a841c1825daabe35728c02a04ecc7289f22。
                                                    
图7. 系统调用被映射为智能合约的调用
可以用xchain-cli查询一下这个交易,./xchain-cli tx query 303c867e195ba464778250b2e7f21a841c1825daabe35728c02a04ecc7289f22,这的确是存储在区块链上的。
  图8. 文件写入对应的Transaction的结构(局部)
甚至,可以在这个文件系统上跑一个sqlite:
                                                     
图9 在区块链上跑SQLite
                                           
   图10. SQLite底层的文件操作映射到Xfs变成合约调用操作
可追溯的文件系统
最后,重点看看这个文件系统和传统文件系统不同的地方:可追溯。
首先,产生一个文件,里面写上“Hello World”,然后,再次在这个文件后面追加一行:”I will be back”。这个可追溯文件系统支持用户在文件名后面加个版本号,比如@1表示最新的版本,@2表示倒数第二个版本。可追溯的效果如下图:
 图11. 可追溯文件系统的效果
    
图12. 实现可追溯的数据结构基础
很多版本管理工具,如Git也可以实现同样的效果,然而借助区块链,我们实现了去中心化的数据一致性、难篡改等特性,并且只用了200行左右的代码,这一切只是超级链能力的冰山一角。我们会持续完善基于智能合约的开发框架和工具链,敬请关注。
附,文中的代码地址:https://github.com/fxsjy/xuper_python