傳統的檔案系統是作業系統的一部分,一般是在核心裡面實現的。區塊鏈系統都執行在使用者態,如何把區塊鏈變成一塊儲存盤呢?這就要用到Fuse(Filesystem in Userspace)了,簡單來說它是一個使用者態檔案系統框架,只要你的程式實現了open、read、write等等一系列介面,就可以虛擬出一個檔案系統。
在超級鏈中,可以透過智慧合約的put_object把資料儲存到區塊鏈上,透過get_object查詢,也可以透過new_iterator遍歷查詢。
設計思路
一個簡單而大膽的想法,就是用檔案的名字作為key,然後把檔案的內容作為value,藉助智慧合約儲存到區塊鏈上,比如put_object(“/mydir/1.txt”, “a long story”)。讀取該檔案,就是呼叫get_object(“/mydir/1.txt”)。列出目錄,就是透過new_iterator(“/mydir”)迴圈遍歷迭代器,拿到所有該字首的檔名。說幹就幹,馬上寫出一個超級鏈合約,實現我們這個檔案系統的核心。
各位看官可能會問,這個合約的功能和redis、leveldb等key-value儲存相比,有什麼特殊之處呢?這個就要說到超級鏈的XuperModel模型了。
在超級鏈裡面的事務模型是XuperModel,它是基於經典的UTXO模型演化而來,經典的UTXO模型只能描述轉賬場景,而XuperModel創新之處在於可以描述更加通用的資料變更。
超級鏈底層的資料多版本機制實現也與資料庫不同。資料庫的一般做法是將邏輯Key+版本號拼接成物理Key,但是這個方式只能保留有限個版本,一旦版本太多,就會導致區間查詢迭代很慢,因為要Scan大量無用的老版本。超級鏈用了一種鏈式雜湊的多版本介面,在狀態樹中Key對應的Value只是雜湊指標,指向賬本中事務的Output欄位,要回溯之前的老版本也只需要透過事務的Input指標再往前回溯。當需要回滾事務或區塊的時候,產生的IO開銷也極低。
接下來,要實現一個模組,這個模組起到“橋樑”的作用,把區塊鏈智慧合約儲存對映成一塊盤,這個就是用到了文章開頭提到的Fuse。
簡單起見,我們用python來實現,python有個庫python-fuse可以幫助我們少寫很多程式碼。下圖貼出了主要的程式碼邏輯,目前的實現沒有做chunk管理,一個檔案就是一個整體。對於隨機讀、隨機寫的實現比較簡單粗暴。
見證奇蹟的時刻,執行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/
同時,在xfs_demo的控制檯上,看到了如下輸出,這個是系統呼叫觸發的,我們可以看到一次寫入操作產生了區塊鏈上的一個交易,有交易id: 303c867e195ba464778250b2e7f21a841c1825daabe35728c02a04ecc7289f22。
可以用xchain-cli查詢一下這個交易,./xchain-cli tx query 303c867e195ba464778250b2e7f21a841c1825daabe35728c02a04ecc7289f22,這的確是儲存在區塊鏈上的。
甚至,可以在這個檔案系統上跑一個sqlite:
可追溯的檔案系統
最後,重點看看這個檔案系統和傳統檔案系統不同的地方:可追溯。
首先,產生一個檔案,裡面寫上“Hello World”,然後,再次在這個檔案後面追加一行:”I will be back”。這個可追溯檔案系統支援使用者在檔名後面加個版本號,比如@1表示最新的版本,@2表示倒數第二個版本。可追溯的效果如下圖:
很多版本管理工具,如Git也可以實現同樣的效果,然而藉助區塊鏈,我們實現了去中心化的資料一致性、難篡改等特性,並且只用了200行左右的程式碼,這一切只是超級鏈能力的冰山一角。我們會持續完善基於智慧合約的開發框架和工具鏈,敬請關注。
附,文中的程式碼地址:https://github.com/fxsjy/xuper_python