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

2023-10-25 08:31

本文主要是介绍200行代码实现一个可追溯的文件系统,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

难篡改、可追溯,这两个性质是区块链被广泛认可的良好特性。

最早比特币只实现了交易转账的可追溯,如果要实现数据变更的可追溯,就需要编写智能合约来实现了,可惜大多数区块链系统的合约开发都不是很好用,这个门槛把很多试图体验区块链的人挡在了门外。

如果能把区块链变成一块硬盘,放在里面的文件自动就具备了“难篡改、可追溯”的性质,是不是很酷?本文将介绍如何基于百度超级链来来实现这样一个文件系统,主要的代码只有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。 

图5. 把合约空间mount为一块盘

简单起见,我们用python来实现,python有个库python-fuse可以帮助我们少写很多代码。下图贴出了主要的代码逻辑,目前的实现没有做chunk管理,一个文件就是一个整体。对于随机读、随机写的实现比较简单粗暴。

图4  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/

图5 用起来本地文件系统体验一致,丝般顺滑

同时,在xfs_demo的控制台上,看到了如下输出,这个是系统调用触发的,我们可以看到一次写入操作产生了区块链上的一个交易,有交易id: 303c867e195ba464778250b2e7f21a841c1825daabe35728c02a04ecc7289f22。

图6 系统调用被映射为智能合约的调用

可以用xchain-cli查询一下这个交易,./xchain-cli tx query 303c867e195ba464778250b2e7f21a841c1825daabe35728c02a04ecc7289f22,这的确是存储在区块链上的。

图7 文件写入对应的Transaction的结构(局部)

甚至,可以在这个文件系统上跑一个sqlite:

图8 在区块链上跑SQLite

图9 SQLite底层的文件操作映射到Xfs变成合约调用操作

可追溯的文件系统

最后,重点看看这个文件系统和传统文件系统不同的地方:可追溯。

首先,产生一个文件,里面写上“Hello World”,然后,再次在这个文件后面追加一行:”I will be back”。这个可追溯文件系统支持用户在文件名后面加个版本号,比如@1表示最新的版本,@2表示倒数第二个版本。可追溯的效果如下图:

图10 可追溯文件系统的效果

图11 实现可追溯的数据结构基础

很多版本管理工具,如Git也可以实现同样的效果,然而借助区块链,我们实现了去中心化的数据一致性、难篡改等特性,并且只用了200行左右的代码,这一切只是超级链能力的冰山一角。我们会持续完善基于智能合约的开发框架和工具链,敬请关注。

附,文中的代码地址(点击阅读原文直达):

https://github.com/fxsjy/xuper_python

如果你是区块链开发者、技术发烧友,

欢迎加入超级链开发者社群。

加群方式:添加百度超级链小助手微信(image-baidu),

回复:我是开发者

这篇关于200行代码实现一个可追溯的文件系统的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/281310

相关文章

Spring StateMachine实现状态机使用示例详解

《SpringStateMachine实现状态机使用示例详解》本文介绍SpringStateMachine实现状态机的步骤,包括依赖导入、枚举定义、状态转移规则配置、上下文管理及服务调用示例,重点解... 目录什么是状态机使用示例什么是状态机状态机是计算机科学中的​​核心建模工具​​,用于描述对象在其生命

Spring Boot 结合 WxJava 实现文章上传微信公众号草稿箱与群发

《SpringBoot结合WxJava实现文章上传微信公众号草稿箱与群发》本文将详细介绍如何使用SpringBoot框架结合WxJava开发工具包,实现文章上传到微信公众号草稿箱以及群发功能,... 目录一、项目环境准备1.1 开发环境1.2 微信公众号准备二、Spring Boot 项目搭建2.1 创建

IntelliJ IDEA2025创建SpringBoot项目的实现步骤

《IntelliJIDEA2025创建SpringBoot项目的实现步骤》本文主要介绍了IntelliJIDEA2025创建SpringBoot项目的实现步骤,文中通过示例代码介绍的非常详细,对大家... 目录一、创建 Spring Boot 项目1. 新建项目2. 基础配置3. 选择依赖4. 生成项目5.

Linux下删除乱码文件和目录的实现方式

《Linux下删除乱码文件和目录的实现方式》:本文主要介绍Linux下删除乱码文件和目录的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux下删除乱码文件和目录方法1方法2总结Linux下删除乱码文件和目录方法1使用ls -i命令找到文件或目录

SpringBoot+EasyExcel实现自定义复杂样式导入导出

《SpringBoot+EasyExcel实现自定义复杂样式导入导出》这篇文章主要为大家详细介绍了SpringBoot如何结果EasyExcel实现自定义复杂样式导入导出功能,文中的示例代码讲解详细,... 目录安装处理自定义导出复杂场景1、列不固定,动态列2、动态下拉3、自定义锁定行/列,添加密码4、合并

mybatis执行insert返回id实现详解

《mybatis执行insert返回id实现详解》MyBatis插入操作默认返回受影响行数,需通过useGeneratedKeys+keyProperty或selectKey获取主键ID,确保主键为自... 目录 两种方式获取自增 ID:1. ​​useGeneratedKeys+keyProperty(推

Spring Boot集成Druid实现数据源管理与监控的详细步骤

《SpringBoot集成Druid实现数据源管理与监控的详细步骤》本文介绍如何在SpringBoot项目中集成Druid数据库连接池,包括环境搭建、Maven依赖配置、SpringBoot配置文件... 目录1. 引言1.1 环境准备1.2 Druid介绍2. 配置Druid连接池3. 查看Druid监控

Linux在线解压jar包的实现方式

《Linux在线解压jar包的实现方式》:本文主要介绍Linux在线解压jar包的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux在线解压jar包解压 jar包的步骤总结Linux在线解压jar包在 Centos 中解压 jar 包可以使用 u

c++ 类成员变量默认初始值的实现

《c++类成员变量默认初始值的实现》本文主要介绍了c++类成员变量默认初始值,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录C++类成员变量初始化c++类的变量的初始化在C++中,如果使用类成员变量时未给定其初始值,那么它将被

Qt使用QSqlDatabase连接MySQL实现增删改查功能

《Qt使用QSqlDatabase连接MySQL实现增删改查功能》这篇文章主要为大家详细介绍了Qt如何使用QSqlDatabase连接MySQL实现增删改查功能,文中的示例代码讲解详细,感兴趣的小伙伴... 目录一、创建数据表二、连接mysql数据库三、封装成一个完整的轻量级 ORM 风格类3.1 表结构