IPFS初探和思索

莫名奇妙的接手了區(qū)塊鏈業(yè)務(wù)的探索,技術(shù)棧選型就成了當(dāng)務(wù)之急。這篇隨便,因?yàn)槭翘接懠夹g(shù)選型,所以我略過(guò)業(yè)務(wù)的部分,也跳過(guò)區(qū)塊鏈的一些列的科普,比如Merkle根和pbft之類(lèi),而是簡(jiǎn)單記錄我在技術(shù)選型上的分支探索的筆記和當(dāng)前技術(shù)水平下的一些思考,以便日后回溯和復(fù)盤(pán)。

技術(shù)需求:利用區(qū)塊鏈技術(shù)實(shí)現(xiàn)一個(gè)安全不可篡改多備份的分布式數(shù)據(jù)庫(kù),去保存一些高價(jià)值數(shù)據(jù)

好吧,不提這個(gè)需求是否符合區(qū)塊鏈的“核心價(jià)值觀”,組織說(shuō)已經(jīng)決定,就這么做吧。 對(duì)于這個(gè)需求,主流的兩個(gè)技術(shù)選型,一是fabric, 利用它的key value數(shù)據(jù)庫(kù),然后一切的trick集中在如何巧妙的設(shè)計(jì)key,以便后續(xù)查詢可以優(yōu)化。另一個(gè)思路是以太坊搭建一個(gè)Dapp, 搞定這個(gè)需求也是有可行性,可是感覺(jué)又要去研究solidity,腦殼疼。? 我抱怨了一波,不就是存?zhèn)€數(shù)據(jù),你搭建個(gè)私有g(shù)it不就結(jié)了,非要區(qū)塊鏈么。。。。

查閱資料,突然發(fā)現(xiàn)有一個(gè)東西,可以很好的匹配上述的需求,那就是IPFS (星際文件系統(tǒng))。IPFS是p2p文件共享系統(tǒng),遠(yuǎn)景宏達(dá),旨在從根本上改變信息在全球及全球范圍內(nèi)分發(fā)的方式,可以說(shuō)最終期望取代http協(xié)議。不討論它的終極野心,從技術(shù)看,類(lèi)似于區(qū)塊鏈,它也是一組技術(shù)的綜合體,包括BitTorrent, git ,分布式哈希表,自驗(yàn)證文件系統(tǒng),Merkle DAG/Tree。 (注:分割線之間的內(nèi)容大量引自參考文獻(xiàn)[1])



HTTP非常適合加載網(wǎng)站,但它并不是為傳輸大量數(shù)據(jù)(例如音頻和視頻文件)而設(shè)計(jì)的。這些限制可能使替代文件共享系統(tǒng)(如Napster(音樂(lè))和BitTorrent(電影以及幾乎所有東西))的出現(xiàn)和主流成功。IPFS嘗試通過(guò)新穎的p2p文件共享系統(tǒng)解決客戶端-服務(wù)器模型和HTTP Web的缺陷。

流行的文件共享系統(tǒng)Bittorrent能夠依靠創(chuàng)新的數(shù)據(jù)交換協(xié)議成功地協(xié)調(diào)數(shù)百萬(wàn)個(gè)節(jié)點(diǎn)之間的數(shù)據(jù)傳輸,但僅限于torrent生態(tài)系統(tǒng)。IPFS實(shí)現(xiàn)了該協(xié)議的通用版本,稱(chēng)為BitSwap,它可作為任何類(lèi)型的數(shù)據(jù)的市場(chǎng)。

merkle DAG是Merkle樹(shù)和有向無(wú)環(huán)圖(DAG)的混合。默克爾樹(shù)可確保在p2p網(wǎng)絡(luò)上交換的數(shù)據(jù)塊是正確,未損壞和未更改的。通過(guò)使用密碼哈希函數(shù)組織數(shù)據(jù)塊來(lái)完成此驗(yàn)證。這只是一個(gè)接受輸入并計(jì)算與該輸入相對(duì)應(yīng)的唯一字母數(shù)字字符串(哈希)的函數(shù)。容易檢查輸入是否會(huì)導(dǎo)致給定的哈希,但是很難從哈希中猜測(cè)輸入。? Merkle DAG結(jié)構(gòu)的另一個(gè)強(qiáng)大功能是,它允許您構(gòu)建分布式版本控制系統(tǒng)(VCS)。最受歡迎的示例是Github,它使開(kāi)發(fā)人員可以輕松地同時(shí)在項(xiàng)目上進(jìn)行協(xié)作。Github上的文件使用merkle DAG存儲(chǔ)和版本控制。它允許用戶獨(dú)立地復(fù)制和編輯文件的多個(gè)版本,存儲(chǔ)這些版本,然后將編輯內(nèi)容與原始文件合并。

IPFS的另一個(gè)基本組成部分是自認(rèn)證文件系統(tǒng)(SFS)。它是一種分布式文件系統(tǒng),不需要特殊權(quán)限即可進(jìn)行數(shù)據(jù)交換。這是“自我認(rèn)證”,因?yàn)樘峁┙o客戶端的數(shù)據(jù)通過(guò)文件名(由服務(wù)器簽名)進(jìn)行認(rèn)證。(隱患:您可以通過(guò)本地存儲(chǔ)的透明性來(lái)安全地訪問(wèn)遠(yuǎn)程內(nèi)容。) IPFS在此概念的基礎(chǔ)上創(chuàng)建了行星際名稱(chēng)空間(IPNS)。它是一個(gè)使用公用密鑰加密技術(shù)對(duì)網(wǎng)絡(luò)用戶發(fā)布的對(duì)象進(jìn)行自我認(rèn)證的SFS 。IPFS上的所有對(duì)象都可以唯一標(biāo)識(shí),但這也擴(kuò)展到了節(jié)點(diǎn)。網(wǎng)絡(luò)上的每個(gè)節(jié)點(diǎn)都有一組公用密鑰,專(zhuān)用密鑰和一個(gè)節(jié)點(diǎn)ID,該ID是其公用密鑰的哈希。因此,節(jié)點(diǎn)可以使用其私鑰對(duì)發(fā)布的任何數(shù)據(jù)對(duì)象進(jìn)行“簽名”,并且可以使用發(fā)送者的公鑰來(lái)驗(yàn)證此數(shù)據(jù)的真實(shí)性。?

那么,為什么所有這些都很重要?

IPFS提供高吞吐量,低延遲,數(shù)據(jù)分發(fā)。它也是分散和安全的。這打開(kāi)了幾個(gè)有趣且令人興奮的用例。它可用于將內(nèi)容傳送到網(wǎng)站,使用自動(dòng)版本控制和備份在全球存儲(chǔ)文件,促進(jìn)安全的文件共享和加密的通信。



結(jié)束了IPFS的科普之后,我就在想,我能否基于ipfs搭建一個(gè)私網(wǎng),這樣就可以完美解決需求。操作如下;(以下內(nèi)容大量參考文獻(xiàn)[2])

1) 搭建一個(gè)ipfs節(jié)點(diǎn):

# 拉取go-ipfs鏡像

docker pull ipfs/go-ipfs:latest

# 配置staging和data的volume映射文件

ipfs_staging=/tmp/ipfs_staging

mkdir -p $ipfs_staging

ipfs_data=/tmp/ipfs_data

mkdir -p $ipfs_data

# 啟動(dòng)ipfs節(jié)點(diǎn)

docker run -d --name ipfs_host \

? ?-v $ipfs_staging:/export \

? ?-v $ipfs_data:/data/ipfs \

? ? -p 4001:4001 \

? -p 127.0.0.1:8080:8080 \

? ?-p 127.0.0.1:5001:5001 \

? ?ipfs/go-ipfs:latest

啟動(dòng)docker :?docker logs -f ipfs_host

在瀏覽器地址欄輸入這個(gè)地址?http://localhost:5001/webui?,會(huì)自動(dòng)跳轉(zhuǎn)到ipfs的explorer的web ui界面。

2) 搭建單節(jié)點(diǎn)私網(wǎng), 生成swarm key



# 關(guān)閉前面啟動(dòng)的ipfs節(jié)點(diǎn)

docker stop ipfs_host

docker rm -f ipfs_host

# 配置staging和data的volume映射文件

ipfs_staging=/tmp/ipfs_staging

mkdir -p $ipfs_staging

ipfs_data=/tmp/ipfs_data

mkdir -p $ipfs_data

# 拉取ipfs swarm key工具 ,也可以直接用

go get github.com/Kubuxu/go-ipfs-swarm-key-gen/ipfs-swarm-key-gen

# 生成swarm key

$GOPATH/bin/ipfs-swarm-key-gen > $ipfs_data/swarm.key

# 啟動(dòng)ipfs節(jié)點(diǎn)

docker run -d --name ipfs_host \

?-v $ipfs_staging:/export \

?-v $ipfs_data:/data/ipfs \

?-p 4001:4001 \

?-p 127.0.0.1:8080:8080 \

?-p 127.0.0.1:5001:5001 \

? ?ipfs/go-ipfs:latest

之后,移除默認(rèn)的bootstrap

docker exec ipfs_host ipfs bootstrap rm --all

3) 添加新的節(jié)點(diǎn)

第一個(gè)私有節(jié)點(diǎn)啟動(dòng)后,可以再添加若干個(gè)新的節(jié)點(diǎn),這樣一個(gè)多節(jié)點(diǎn)的IPFS私有網(wǎng)絡(luò)就搭好了。添加新節(jié)點(diǎn)時(shí)要注意:1)在添加新節(jié)點(diǎn)的之前,要把前面生成的swarm key復(fù)制到ipfs_data目錄下;2)在新節(jié)點(diǎn)啟動(dòng)后,要指定bootstrap信息。

new_peer_suffix=_1

ipfs_staging=/tmp/ipfs_staging$new_peer_suffix

mkdir -p $ipfs_staging

ipfs_data=/tmp/ipfs_data$new_peer_suffix

mkdir -p $ipfs_data

cp /tmp/ipfs_data/swarm.key $ipfs_data/swarm.key

# 啟動(dòng)ipfs節(jié)點(diǎn)

docker run -d --name ipfs_host$new_peer_suffix \

? -v $ipfs_staging:/export \

? -v $ipfs_data:/data/ipfs \

? -p 4101:4001 \

? -p 127.0.0.1:8180:8080 \

? -p 127.0.0.1:5101:5001 \

? ? ipfs/go-ipfs:latest

當(dāng)然,2和3的整個(gè)過(guò)程也可以寫(xiě)個(gè)腳本搞定,start.sh? 注意后面要有個(gè)參數(shù),值為啟動(dòng)的節(jié)點(diǎn)數(shù)目 ,stop.sh也可以寫(xiě)一個(gè),就是前面的docker stop, docker rm, 比較簡(jiǎn)單,就不贅述了。

#!/bin/bash

function bootIpfsPeer {

? ? index=$1

? ? hostName=ipfs_host_${index}

? ? ipfs_staging=/tmp/ipfs_staging_${index}

? ? rm -rf $ipfs_staging

? ? mkdir -p $ipfs_staging

? ? ipfs_data=/tmp/ipfs_data_${index}

? ? rm -rf $ipfs_data

? ? mkdir -p $ipfs_data

? ? cp ./data/swarm.key $ipfs_data

? ? echo "Creating ${hostName} ..."

? ? sudo docker run -d --name ${hostName} \

? ? ? ? -v ${ipfs_staging}:/export \

? ? ? ? -v ${ipfs_data}:/data/ipfs \

? ? ? ? -p $((4001 + index*10)):4001 \

? ? ? ? -p $((5001 + index*10)):5001 \

? ? ? ? -p 127.0.0.1:$((8080 + index)):8080 \

? ? ? ? ipfs/go-ipfs:latest

? ? echo "Remove bootstrap for ${hostName} ..."

? ? docker exec ${hostName} ipfs bootstrap rm --all

}

function setupIpfsNetwork {

? ? for (( i=0; i<$1; i++ ))

? ? do

? ? ? ? bootIpfsPeer ${i}

? ? done

}

function createSwarmKey {

? ? rm -rf ./data

? ? mkdir -p ./data

? ? cp ./swarm.key ./data/swarm.key

}

function rmIpfsHosts {

? ? dockerContainers=$(docker ps -a | awk '$2~/ipfs/ {print $1}')

? ? if [ "$dockerContainers" != "" ]; then

? ? ? echo "Deleting existing docker containers ..."

? ? ? docker rm -f $dockerContainers

? ? fi

}

function showResult {

? ? docker ps -a

}

function main {

? ? rmIpfsHosts

? ? createSwarmKey

? ? setupIpfsNetwork $1

? ? showResult

}

if [ "$#" -ne 1 ]; then

? ? echo "ERROR: Peers number must be set for private ipfs network"

? ? echo "usage: start.sh \${peerNumber}"

? ? echo "For example: Run this command"

? ? echo "? ? ? ? ? ? ? ? ./start.sh 3"

? ? echo "? ? ? ? ? ? A private ipfs network with 3 peers will be setup locally"

? ? exit 1

else

? ? main $1

fi


4) 網(wǎng)絡(luò)搭建完畢,終于到了可以測(cè)試的時(shí)候了

首先,進(jìn)入一個(gè)節(jié)點(diǎn)

docker exec -it ipfs_host /bin/sh

# 上傳文件,文件各種格式都支持,你大可以傳個(gè)圖片啥的,這里當(dāng)然是使用新手必備hello world

echo "hello world" > hello.txt

ipfs add hello.txt??


然后那個(gè) hash碼就成了這個(gè)文件的唯一標(biāo)識(shí)。。。。各種查看方法,比如ipfs cat,或者瀏覽器 查看http://localhost:8080/ipfs/[------IPFS_URL-----]



那么問(wèn)題來(lái)了, 一通操作猛如虎,需求滿足了么?


首先,安全性,私網(wǎng)都用一個(gè)swarm key, 分發(fā)和管理秘鑰就是個(gè)嚴(yán)重的問(wèn)題

其次,批量的查詢,如果不做個(gè)緩存的中間層索引,還是0

最后,身份管理,權(quán)限管理啊這些最重要的部分,目前看來(lái)都沒(méi)有直接的解決方案

總體看來(lái),想搭建一個(gè)ipfs私網(wǎng)就解決問(wèn)題,看來(lái)行不通。還是得fabric搭建聯(lián)盟鏈。但是ipfs作為鏈上鏈下的解決方案的數(shù)據(jù)層,似乎很有潛力。



參考文獻(xiàn):

1)IPFS星際大陸,《最全解析:一文入門(mén)IPFS》,https://www.8btc.com/media/572061

2) 安心讀書(shū),《MAC上搭建私有IPFS網(wǎng)絡(luò)》,https://blog.csdn.net/weixin_41459401/article/details/84563258

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容