IPFS協議棧筆記

身份層:管理節點身份生成和驗證

網絡層:管理與其他節點的連接、使用多種底層網絡協議

路由層:以分佈式哈希表維護路由信息以定位特定的對等節點和對象。響應本地和遠端節點發出的查詢請求。

交換層:一種支持有效塊分配的新型塊交換協議BitSwap,模擬可信時場,弱化數據複製,防作弊

對象層:具有基於Merkle DAG所構建的對象層,具有內容尋址,防冗餘特性

文件層:類似Git的版本化文件系統

命名層:具有自驗特性的可變名稱系統

 

身份層

標識IPFS網絡的節點。在節點首次建立時,節點之間首先交換公鑰,並且進行身份信息驗證,比如:檢查hash(other.PublicKey)的值是否等於other.NodeId的值。如果校驗不通過,則用戶信息不匹配,節點立即終止連接。

有兩個優勢:

根據需求選擇最佳算法,隨着功能的變化而演變。

 

網絡層

IPFS網絡堆棧的特點:

傳輸:IPFS兼容現有的主流傳輸協議,WebRTCDataChannels或uTP

可靠性:使用uTP和sctp來保障,這兩種協議可以動態調整網絡狀態

可連接性:使用ICE等NAT穿越技術來實現廣域網的可連接性

完整性:使用哈希校驗檢查數據完整性,IPFS所有數據塊都有唯一的哈希

可驗證性:使用數據發送者的公鑰及HMAC消息認證碼來檢查消息的真實性

 

IPFS採用multiaddr的格式來表示目的地址和其使用的協議,以此來兼容和擴展未來可能出現的其他網絡協議。

IPFS遵循覆蓋網絡的設計理念。首先虛擬出類似網關的IP地址,然後把數據包轉發到Host物理服務器地址,最終通過路由和交換到達另一個HOST服務器的IP地址

路由層

路由層用於查找同伴節點的網絡地址;專門用於服務特定對象的對等節點。IPFS數據結構基於S/Kadmlia和Coral技術的分佈式鬆散哈希表。DSHT的接口位於libp2p模塊中,IPFS路由實現了3中基本功能:內容路由、節點路由和節點存儲.

交換層

IPFS中的BitSwap協議是協議實驗的一項創新設計,利用信用機制在節點之間進行數據交換。BitSwap不侷限於一個種子文件中的數據塊。BitSwap協議中存在一個數據交換時場,包含各個節點想要獲取的所有塊數據,這些塊來自文件系統中完全不相關的文件,同時這個市場是由IPFS網絡中所有節點組成的。

BitSwap協議

BitSwap協議主要負責兩件事情:向其他節點請求需要的數據塊列表(want_list)和爲其他節點提供已有的數據塊列表(have_list)。當我們需要向其他節點請求數據或爲其他節點提供數據塊時,都會發送BitSwap message消息:want_list和對應數據塊。

BitSwap系統重要模塊:

需求管理器(Want-Manager):節點請求時在本地返回相應的結果或者發出合適的請求;

決策引擎(Desction-Engine):如何爲其他節點分配資源,當接待你接收包含want_list的消息時,會被轉發到決策引擎,引擎根據節點的BitSwap賬單。

生命週期:

狀態開放(Open):對等節點間開放待發送Bitswap賬單狀態,直到建立連接

數據發送(Sending):節點間發送want_list和數據塊

連接關閉(Close):節點發送完成後斷開連接

節點忽略(Ignored):超時、自定義和信用過分底等因素被忽略

 

BitSwap信用體系

BitSwap協議必須能夠激勵節點去樂於分享數據,即使這個節點暫時沒有數據需求。IPFS根據節點的之間的數據收發建立了一個信用體系:有借有還,再借不難。

  • 發送給其他節點數據可以增加信用值
  • 從其他節點接受數據降低信用值

如果一個節點只接收數據而不分享數據,信用值就會降得很低而被其他節點忽略掉。簡單來講就是:你樂於分享數據,其它節點也樂於發送數據給你,如果你不願意分享,那麼其它節點也不願意給你數據。

 

BitSwap策略

根據上面的信用體系,BitSwap可以採取不同的策略來實現,每一種策略都會對系統的整體性能產生不同的影響。策略的目標是:

  1. 節點數據交換的整體性能和效率最高
  2. 阻止“喫白食”(freeloaders)的現象。就是不能夠只下載數據不上傳數據
  3. 可以有效的防止一些攻擊行爲(比如:女巫攻擊)
  4. 對信任節點建立寬鬆機制(lenient)

IPFS提供一個可參考的策略機制(實際的實現可以有所變化):

每個節點根據和其他節點的收發數據,計算負債率(debt ratio,r) r = bytes_sent / (bytes_recv + 1) 節點根據負債率計算出來和這個節點的數據發送率(P) P (send|r) = 1− 1/(1+exp(6−3r))

根據這兩個函數可以發現,當負債率達到某一個值的時候負債率會急劇下降。

這個模型表達的意義:如果一個節點只接受數據不分享數據,別人發送給它數據的概率會越來越低(到達某一個值後就會急劇降低接近0),如果節點持續保持分享數據,別的節點向你發送數據的概率就會越來越大。

 

BitSwap賬單

BitSwap節點會記錄下來和其他節點通信的賬單(數據收發),可以保持節點間數據交換的歷史和防止篡改。當兩個節點之間建立連接的時候,BitSwap會相互交換賬單信息,如果賬單不匹配,則清除重新記賬。惡意節點可能會故意“丟失”賬單,以希望清除掉自己的債務。其它交互節點會把這些都記下來,如果總是發生,節點就會被拒絕。

 

對象層

基於分佈式哈希表DHT和BitSwap技術,IPFS期望構造一個龐大的點對點系統,用於快速、穩健地存儲和分發數據塊。

IPFS使用Merkle DAG技術構建了一個有向無環圖數據結構,用於存儲對象數據。這也是Git使用的數據結構,Merkle DAG爲IPFS提供了很多有用的屬性,包括:

1、內容可尋址:所有內容由多重哈希校驗並唯一標識。

2、防止篡改:所有內容都通過哈希校驗,如果數據被篡改,IPFS網絡將能檢測到。

3、重複數據刪除:相同內容有相同哈希,只存儲一次,對索引對象特別有用。


本地對象

IPFS客戶端需要一個本地存儲器,一個外部系統可以爲IPFS管理的對象存儲以及檢索本地原始數據。存儲器的類型根據節點使用案例而已,在大多數情況下,這個存儲器只是硬盤空間的一部分(不是被本地的leveldb來管理,就是直接被IPFS客戶端管理),在其他的情況下,例如非持久性緩存,存儲器就是RAM的一部分。

對象鎖定

希望對某個對象數據進行長期存儲的節點可以執行鎖定操作。以此保證此對象被保存在了該節點的本地存儲器上,同時也可以遞歸地鎖定所有相關的派生對象,這對長期存儲完整的對象文件特別有用。

發佈對象

IPFS是全球分佈的文件系統,DHT使用內容哈希尋址技術,使發佈對象是公平的,安全的,完全分佈式的。任何人都可以發佈對象,只需要將對象的Key加入到DHT中,並且對象是通過P2P傳輸的方式加入進去,然後把訪問路徑給其他的用戶。

 

加密操作改變了對象的哈希值,定義了一個不同新的對象結構,IPFS自動的驗證簽名機制,用戶自定義的私鑰加解密數據都爲對象數據提供了安全保證。同時,加密數據的鏈式關係也同樣被保護着,因爲沒有解密密鑰就無法遍歷整個鏈式對象結構。

 

文件層

PFS定義了一組對象,用於在Merkle DAG之上對版本化文件系統進行建模。這個對象模型類似於著名版本控制軟件Git的數據結構:

  • 塊(block):一個可變大小的數據塊。
  • 列表(list):一個塊或其他列表的集合。
  • 樹(tree):塊,列表或其他樹的集合。
  • 提交(commit):樹的版本歷史記錄中的快照。

文件對象:BLOB

  blob對象包含一個可尋址的數據單元,表示一個文件,當文件比較小,不需要切片時,就以Blob對象的形式存儲在IPFS網絡之中,如下所示:

 

{
    "data":"some data here", //blobs 無links
}

文件對象:LIST

  list對象由多個連接在一起的Blob組成,通常存儲的是一個大文件。從某種意義上說,list的功能更適合數據互相連接的文件系統。由於list可以包含其他list,所以可能形成包括鏈接列表和平衡樹在內的拓撲結構,如下:

 

{
    "data":["blob","list","blob"],  //lists有一個對象類型的數組作爲數據
    "links":[
        {
            "hash":"XLYkgq61DYaq8Nhkcqy7LcnSA7dSHQ78x",
            "size":189458
        },
        {
            "hash":"XLHBNsgoepUDKL8dkd9Hesa5io9sdxi7n",
            "size":19442
        },
        {
            "hash":"XLWVQKJII8v7dggkfdhHSFlkaw9yjs7dj",
            "size":5286
        } // 在links中lists是沒有名字的
    ]
}

文件對象:TREE

  在IPFS中,Tree對象與Git的tree類似,代表一個目錄,或者一個名字到哈希值的映射表,哈希值表示blob,list,其他的tree,或commit,結構如下:

 

{
    "data":["blob","list","blob"], // trees有一個對象類型的數組作爲數據
    "links":[
        {
            "hash":"XLYkgq61DYaq8Nhkcqy7LcnSA7dSHQ78x",
            "name":"less",
            "size":189458
        },
        {
            "hash":"XLHBNsgoepUDKL8dkd9Hesa5io9sdxi7n",
            "name":"script",
            "size":19442
        },
        {
            "hash":"XLWVQKJII8v7dggkfdhHSFlkaw9yjs7dj",
            "name":"template",
            "size":5286
        } // trees是沒有名字的
    ]
}

文件對象:COMMIT

  IPFS中,commit對象代表任何對象在版本歷史記錄中的一個快照,它與Git的commit也非常類似,但它可以指向任何類型的對象。

版本控制

  commit對象代表着一個對象在歷史版本中的一個特定快照。兩個不同的commit之間相互比較對象數據,可以揭露出兩個不同版本文件系統的區別。IPFS可以實現Git版本控制工具的所有功能,同時也可以兼容Git。

文件系統路徑

  Merkle DAG可以看到,可以使用字符串路徑API遍歷IPFS對象在系統上的文件路徑地址。

將文件分割成LIST和BLOB

  版本控制和分發大文件最主要的挑戰:找到一個正確的方法來將它們分隔成獨立的塊。與其認爲IPFS可以爲每個不同類型的文件提供正確的分隔方法,不如說IPFS提供了以下的幾個可選選擇:

  • 使用Rabin Fingerprints指紋算法來定義比較合適的塊邊界。
  • 使用rsync和rolling-checksum算法,來檢測塊在版本之間的改變。
  • 允許用戶設定文件大小而調整數據塊的分割策略。

路徑查找性能

  基於路徑的訪問需要遍歷整個對象圖,檢索每個對象需要在DHT中查找它的Key值,連接到對等點並檢索對應的數據塊。這是一筆相當大的性能開銷,特別是在查找的路徑具有多個路徑時。IPFS充分考慮了這一點,並設計瞭如下的方式來緩解:

  • 樹緩存(tree cache):由於所有的對象都是哈希尋址的,可以被無限的緩存,另外,tree一般比較小,所以比起blob,IPFS會優先緩存tree。
  • 扁平樹(flattened trees):對於任何給定的tree,一個特殊的扁平樹可以構建一個鏈表,所有對象都可以從這個tree中訪問得到。在扁平樹中name就是一個從原始tree分離的路徑,用斜線分隔。

命名層

       採用DAG的方式生成了一個可以追蹤對象的歷史記錄;但是存在一個問題:當數據對象的內容更新後,同時發生改變的還有內容地址的名稱。需要設計一個在易變環境中保持固定名稱的方案。

自驗證簽名

       在加密環境下、在全局命名空間中,構建可自行認證名稱的方式,模式如下:

       NodeId = hash(node.PubKey),生成IPFS節點信息

       給每個用戶分配一個可變的命名空間,由之前生成的節點ID信息作爲地址名稱,在此路徑下:/ipns/

       一個用戶可以在此路徑下發佈一個用自己私鑰簽名的對象。比如:

      /ipns/XLF2ip4ii9x0wejs23HD2swlddVmas8kd0Ax/ 。

      當其他用戶獲取對象時,他們可以檢測簽名是否與公鑰和節點信息匹配,從而驗證用戶發佈對象的真實性,達到可變狀態的獲取。

人類友好名稱

  IPNS是重新命名地址名稱的好方式,但對人類來說,卻不是十分友好和記憶,因此,IPFS使用下面的技術來增加IPNS的用戶良好度。

1.對等節點鏈接

  遵循自驗證文件系統(SFS)的設計理念,用戶可以將其他用戶節點的對象直接鏈接到自己的命名空間下,這有利於創建一個更信任的網絡:

# Alice links 到 Bob 上
ipfs link /<alice-pk-hash>/friends/bob /<bob-pk-hash>
# Eve links 到 Alice 上
ipfs link /<eve-pk-hash>/friends/alice /<alice-pk-hash>
# Eve 也可以訪問Bob
/<eve-pk-hash>/friends/alice/friends/bob
# 訪問Verisign認證域
/<verisign-pk-hash>/foo.com

2.DNS TXT IPNS記錄

  在現有的DNS系統中添加TXT記錄,這樣能夠通過域名訪問IPFS網絡中的文件對象:

# DNS TXT 記錄
ipfs.benet.ai. TXT "ipfs=XLF2ip4jD3U..."
# 表現爲符號鏈接
ln -s /ipns/XLF2ip4jD3U... /ipns/fs.benet.ai

# IPFS也支持可讀標識符Proquint,可以將二進制編碼翻譯成可讀文件的方法,如下:
# proquint語句
/ipns/dahih-dolij-sozuk-vosah-luvar-fuluh
# 分解爲相應的下面形式
/ipns/KhWwNprxYVxKqpDZ

除此之外,IPFS還提供短地址的命名服務,類似我們現在看到的DNS和WebURL鏈接:

# 用戶可以從下面獲取一個link
/ipns/shorten.er/foobar
# 然後放到自己的命名空間
/ipns/XLF2ipQ4JD3Udex6xKbgeHrhemUtaA9Vm

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章