如何使用星際文件傳輸網絡(IPFS)搭建區塊鏈服務(一)

轉載自:https://qtum.org/zh/blog/ru-he-shi-yong-xing-ji-wen-jian-chuan-shu-wang-luo-ipfs-da-jian-qu-kuai-lian-fu-wu

IPFS(InterPlanetary File System)是一個點對點的分佈式超媒體分發協議,它整合了過去幾年最好的分佈式系統思路,爲所有人提供全球統一的可尋址空間,包括Git、自證明文件系統SFS、BitTorrent和DHT,同時也被認爲是最有可能取代HTTP的新一代互聯網協議。

IPFS用基於內容的尋址替代傳統的基於域名的尋址,用戶不需要關心服務器的位置,不用考慮文件存儲的名字和路徑。我們將一個文件放到IPFS節點中,將會得到基於其內容計算出的唯一加密哈希值。哈希值直接反映文件的內容,哪怕只修改1比特,哈希值也會完全不同。當IPFS被請求一個文件哈希時,它會使用一個分佈式哈希表找到文件所在的節點,取回文件並驗證文件數據。

IPFS是通用目的的基礎架構,基本沒有存儲上的限制。大文件會被切分成小的分塊,下載的時候可以從多個服務器同時獲取。IPFS的網絡是不固定的、細粒度的、分佈式的網絡,可以很好的適應內容分發網絡的要求。這樣的設計可以很好的共享各類數據,包括圖像、視頻流、分佈式數據庫、整個操作系統、模塊鏈、8英寸軟盤的備份,還有靜態網站。

IPFS提供了一個友好的WEB訪問接口,用戶可以通過本機的 IPFS-HTTP 網關http://localhost:5001/ipfs/ 或者 公共的網關http://ipfs.io/ 獲取IPFS網絡中的內容,也可以通過特定的瀏覽器或者插件通過ipfs:/

or fs:/

的方式直接獲取內容。也許在不久的將來,IPFS協議將會徹底替代傳統的HTTP協議。

一、使用IPFS

1.1 安裝

  • $ go get -u -d github.com/ipfs/go-ipfs
  • $ cd GOPATH/src/github.com/ipfs/go-ipfs
  • $ make install

1.2 初始化

  • $ ipfs init

1.3 加入IPFS網絡

  • $ ipfs daemon

1.4 獲取內容

  • $ ipfs cat /ipfs/QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG/readme
  • http://localhost:5001/ipfs/QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG

1.5 發佈內容

  • $ ipfs add hello.jpg
  • IPFS文件還可以抽象成特殊的IPFS目錄,從而標註一個可讀的文件名(透明的映射到IPFS哈希),在訪問的時候會像HTTP一樣獲取一個目錄索引。在IPFS上建立網站的流程和過去一樣,而且把網站加入到IPFS節點的指令只需要一條指令:ipfs add -r yoursitedirectory

1.6 緩存內容到本地

  • $ ipfs pin add -r QmcKi2ae3uGb1kBg1yBpsuwoVqfmcByNdMiZ2pukxyLWD8
  • 緩存到本地的內容不僅可以自己使用,還能爲其他節點提供資源

1.7 IPNS域名訪問

  • IPFS哈希只能用來表示不可變數據,因爲一旦數據改變,哈希值也會改變。從某種意義上來說,這是保持數據持續性的好的設計。但是我們也需要一種方法來標記最新更新網站的哈希,這個方法我們稱作IPNS。
  • IPNS的原理是從域名的TXT記錄裏獲取IPFS哈希地址,然後根據這個哈希地址從IPFS網絡中獲取數據。 比如 http://ipfs.io/ipns/ipfs.git.sexy
  • 接下來IPFS還打算支持Namecoin。Namecoin從理論上完全實現了分佈式Web的去中心化,整體的運行中不再需要中心化的授權。支持了Namecoin的IPFS不再需要ICANN、中心服務器,不受政治干涉,也無需授權證書。

1.8 更多

二、IPFS是如何工作的

2.1 身份驗證

和比特幣相似,每一個節點都會由NodeId(公鑰的哈希值)來標識,節點存儲着公鑰和加密過的私鑰。
首次連接時,節點間交換公鑰,並檢查 hash(other.PublicKey)是否等於other.NodeId。如果沒有,則終止連接。

type NodeId Multihash

type Multihash []byte       

// self-describing cryptographic hash digest



type PublicKey []byte

type PrivateKey []byte

// self-describing keys



type Node struct {

    NodeId NodeID

    PubKey PublicKey

    PriKey PrivateKey

}

2.2 網絡

每個節點與網絡中的相連的其他數百個節點進行定期通信。
IPFS的網絡傳輸具有如下特性:

  • 傳輸: IPFS可以使用任何傳輸協議,如 WebRTC 和 uTP。
  • 可靠性:如果底層網絡不能保證可靠性,IPFS可以使用 uTP 或 SCTP 來保證
  • 連接:IPFS還使用 ICE NAT 穿越技術。
  • 完整性:使用哈希校驗和檢查消息的完整性。
  • 真實性:可以使用發送者的公鑰和HMAC來檢查消息的真實性。

同時IPFS不僅僅是通過IP來連接節點,還支持很多其他協議。IPFS內部使用不同的地址格式來選擇不同的網絡協議。

# an SCTP/IPv4 connection

/ip4/10.20.30.40/sctp/1234/



# an SCTP/IPv4 connection proxied over TCP/IPv4

/ip4/5.6.7.8/tcp/5678/ip4/1.2.3.4/sctp/1234/

2.3 路由

IPFS通過通過基於 S/Kademlia 和 Coral 的 DSHT 來尋找匹配的節點和特定節點的地址信息,IPFS的對象和使用模式的大小類似於 Coral 和 Mainline,因此 IPFS DHT 根據其大小對存儲的值進行區分。 小值(等於或小於1KB)直接存儲在DHT上。對於更大的值,DHT存儲擁有這些塊的節點NodeId。
DSHT的接口定義如下:

type IPFSRouting interface {

    FindPeer(node NodeId)

    // 得到指定節點的地址



    SetValue(key []bytes, value []bytes)

    // 小值可直接存儲在DHT上



    GetValue(key []bytes)

    // 從DHT中獲取值



    ProvideValue(key Multihash)

    // 宣佈此節點可以提供一個大值



    FindValuePeers(key Multihash, min int)

    // 得到擁有特定大值的所以節點

}

2.4 塊交換

在IPFS中,通過使用 BitSwap 協議與其他節點進行塊(block)交換來實現數據分發。
BitSwap 維持着兩個列表,想要獲得的塊和已保存的塊。但與 BitTorrent 不同的是,BitSwap 不限於一個torrent中的塊。BitSwap 節點可以從整個IPFS網絡獲取所需的塊,而不管這些塊屬於哪些文件,這大大提高了下載效率。
同時,網絡中存在一些激勵節點會主動緩存和傳播稀有的文件片段。

2.4.1 信用體系

我們希望所有的節點都樂於分享他們擁有的塊,但某些自私節點只從P2P網絡中獲取塊,而從不做種。
IPFS使用了一套簡單的信用系統來解決這個問題。

  • 從其他節點獲取塊會產生“債務”,向其他節點發送塊可以償還“債務”。
  • 每個節點都記錄與相連節點間的“債務”情況。
  • 欠債越多的節點其優先級越低,如果一個節點只獲取而從不奉獻將會很快被其他節點進行忽略超時操作。

2.4.2 策略

BitSwap 採用的不同策略對整體的演變表現有着非常不同的影響。
在 BitTorrent 中,雖然規定了標準策略,但是也已經實現了許多其他方法,從 BitTyrant (儘可能分享)到BitThief(利用漏洞 並且永遠不會分享),到 PropShare (按比例分享)。
我們需要的策略的目標應該是:

  1. 最大化節點的交易性能和整體交換效率

  2. 防止“吃白食”的情況發生

  3. 有效抵抗其他未知策略

  4. 對受信任的節點限制寬鬆

一種在實踐中可行的策略是一個跟債務率掛鉤的算法
節點的負債率 r = bytes_sent / (bytes_recv + 1)
發送率 P (send|r) = 1− 1/(1+exp(6−3r))
當節點的負債率超過已建立信用額度的兩倍時,發送率迅速降低。

2.4.3 賬單

BitSwap 節點維持與其他節點的傳輸計費賬單,當節點間建立連接時,雙方交換賬單,如果賬單不匹配,則清除已有賬單,重新開始記賬。當然,惡意節點可能會故意丟失賬單,希望清除債務,其他節點可以將其視作不當行爲,並拒絕。
賬單的數據結構如下:

type Ledger struct {

    owner      NodeId

    partner    NodeId

    bytes_sent int

    bytes_recv int

    timestamp  Timestamp

}

2.4.4 接口規範

// Additional state kept

type BitSwap struct {

  ledgers map[NodeId]Ledger

  // Ledgers known to this node, inc inactive



  active map[NodeId]Peer

  // currently open connections to other nodes



  need_list []Multihash

  // checksums of blocks this node needs



  have_list []Multihash

  // checksums of blocks this node has

}



type Peer struct {

  nodeid NodeId

  ledger Ledger

  // Ledger between the node and this peer



  last_seen Timestamp

  // timestamp of last received message



  want_list []Multihash

  // checksums of all blocks wanted by peer

  // includes blocks wanted by peer’s peers

}



// Protocol interface:

interface Peer {

  open (nodeid :NodeId, ledger :Ledger);

  send_want_list (want_list :WantList);

  send_block (block :Block) -> (complete :Bool);

  close (final :Bool);

}

2.5 Merkle DAG

DHT 和 BitSwap 技術讓 IPFS形成一個用於快速而強大的存儲和分發塊的 P2P 系統,。
在此之上,IPFS還構建了一種有向無環圖 Merkle DAG,使用嵌入數據源中的目標哈希散列構建對象之間的鏈接。Merkle DAGs 爲IPFS提供了許多有用的屬性,包括:

  1. 內容尋址:所有內容(包括鏈接)都由其多哈希校驗和進行唯一標識。

  2. 防篡改:所有內容都使用其校驗和進行驗證。如果數據被篡改或損壞,則IPFS會檢測到該數據。

  3. 去冗餘:所有內容完全相同的對象,只存儲一次。這對索引對象特別有用,比如git tree和commits,或者是公共部分的數據。

IPFS對象的定義如下:

type IPFSLink struct {

    Name string
    // name or alias of this link

    Hash Multihash

    // cryptographic hash of target

    Size int

    // total size of target

}



type IPFSObject struct {

  links []IPFSLink

  // array of links

  data []byte

  // opaque content data

}

Merkle DAG 是一種非常靈活的數據存儲方式,唯一的要求是 a) 使用內容尋址 b) 使用上述編碼格式。

這使得我們可以用路徑的方式訪問對象, /ipfs//
比如 /ipfs/XLYkgq61DYaQ8NhkcqyU7rLcnSa7dSHQ16x/test/foo.txt

2.6 文件系統

在 Merkle DAG 之上,IPFS還定義了一組對象用於對版本化文件系統進行建模。
這個對象模型類似於Git:

  1. block:可變大小的數據塊。

  2. list:塊或其他列表的集合。

  3. tree:塊、列表或其他樹的集合。

  4. commit:樹的版本歷史中的快照。

2.6.1 blob

blob 對象包含了可尋址的數據單元,表示一個文件。

{

"data": "some data here",

// blobs 是沒有 link 的

}

一個IPFS文件由 blobs 和 lists 構成

2.6.2 list

list 對象將很多去重的 blobs 連接到一起,包含了一組有序的 blob 或 list 對象。

{

    "data": ["blob", "list", "blob"],

    // 列表裏的數據類型和links裏面的一一對應



    "links": [

        { "hash": "XLYkgq61DYaQ8NhkcqyU7rLcnSa7dSHQ16x",

        "size": 189458 },

        { "hash": "XLHBNmRQ5sJJrdMPuu48pzeyTtRo39tNDR5",

        "size": 19441 },

        { "hash": "XLWVQDqxo9Km9zLyquoC9gAP8CL1gWnHZ7z",

        "size": 5286 }

        // lists have no names in links

    ]

}

2.6.3 tree

tree 對象代表一個路徑,內容包括 blob、list、tree、commit,同時標記了對象的名稱。

{

    "data": ["blob", "list", "blob"],

    // trees have an array of object types as data

    "links": [

        { "hash": "XLYkgq61DYaQ8NhkcqyU7rLcnSa7dSHQ16x",

          "name": "less", "size": 189458 },

        { "hash": "XLHBNmRQ5sJJrdMPuu48pzeyTtRo39tNDR5",

          "name": "script", "size": 19441 },

        { "hash": "XLWVQDqxo9Km9zLyquoC9gAP8CL1gWnHZ7z",

          "name": "template", "size": 5286 }

          // trees do have names

    ]

}

2.6.4 commit

commit 對象代表對象的歷史快照。

{

    "data": {

        "type": "tree",

        "date": "2014-09-20 12:44:06Z",

        "message": "This is a commit message."

    },

    "links": [

        { "hash": "XLa1qMBKiSEEDhojb9FFZ4tEvLf7FEQdhdU",

          "name": "parent", "size": 25309 },

        { "hash": "XLGw74KAy9junbh28x7ccWov9inu1Vo7pnX",

          "name": "object", "size": 5198 },

        { "hash": "XLF2ipQ4jD3UdeX5xp1KBgeHRhemUtaA8Vm",

          "name": "author", "size": 109 }

    ]

}

2.7 命名和可變狀態

到目前爲止,IPFS堆棧形成了構建內容尋址對象 DAG 的P2P交換。它可以用於發佈和檢索不可變的對象,甚至可以跟蹤這些對象的版本歷史。但是,仍缺少一個關鍵組件:可變命名。沒有它,用戶就得在IPFS系統外獲取到新的內容地址了。

2.7.1 自驗證命名

  1. 定義節點的NodeId爲該節點公鑰的哈希

  2. 通過 /ipns/的方式可以訪問該節點下的內容

  3. 當其他節點從該節點獲取文件時,可以驗證其公鑰和NodeId是否匹配

通過自驗證命名,我們可以實現這樣的訪問效果
/ipns//docs/test.md 而不必用 /ipfs/ 這樣的方式

2.7.2 更加友好的命名方式

自驗證命名雖然解決了一些問題,但對用戶來說還不夠友好, IPFS提供瞭如下解決方案:

  1. 節點鏈接
    通過執行 ipfs link //friends/bob /
    便可將 bob 節點鏈接到 alice 節點的 friends/bob 路徑下,這樣只需要知道alice的地址就可以訪問bob了

  2. 域名訪問
    IPNS可以從域名的TXT記錄裏獲取IPFS哈希地址,然後根據這個哈希地址從IPFS網絡中獲取數據
    例如我們設置 ipfs.benet.ai 的TXT記錄爲”ipfs=XLF2ipQ4jD3U …”,
    訪問 /ipns/ipfs.benet.ai 便相當於 ipns/XLF2ipQ4jD3U …

  3. Proquint可發音方案
    IPNS支持將哈希地址譯成可發音的單詞
    例如 /ipns/dahih-dolij-sozuk-vosah-luvar-fuluh
    將解析爲 /ipns/KhAwNprxYVxKqpDZ

  4. 短地址服務
    以shorten.er爲例,用戶可以獲得一個指向特定地址的鏈接
    例如 /ipns/shorten.er/foobar
    將解析爲 /ipns/XLF2ipQ4jD3UdeX5xp1KBgeHRhemUtaA8Vm
    這時shorten.er就類似於我們今天使用的DNS服務器了。

3. 基於IPFS的應用

ipfs.pics - 免費的永久圖牀,上傳和分享你的圖片。
Orbit Chat - 基於IPFS的去中心化聊天室,用戶可以自由創建和加入channel並參與討論。
Neocities - 免費幫助人們創作和發佈網頁的組織,將用戶上傳的網頁永久存儲在IPFS網絡中,即使Neocities關閉了,人們仍然可以在IPFS網絡中瀏覽到這些創作。
AKASHA - 基於IPFS和以太坊的下一代社交博客平臺。
git-ipfs-rehost - 將你的git倉庫託管在IPFS網絡上。
Global Upload - 文件傳輸服務
IPFS SEARCH - 搜索IPFS網絡中的內容

4. IPFS與區塊鏈技術的結合

IPFS彌補了現有區塊鏈系統在文件存儲方面的短板,將IPFS的永久文件存儲和區塊鏈的不可篡改、時間戳證明特性結合,非常適合應用於 保護版權、身份證明、來源證明等方面。
同時用基於區塊鏈的代幣來激勵IPFS節點存儲數據也是最好的選擇。
在去中心化的世界裏,QTUM智能合約提供各種邏輯服務,IPFS提供文件資源,兩者結合,共同構建去中心化的網絡世界。

5. 打賞地址

**比特幣:**1FcbBw62FHBJKTiLGNoguSwkBdVnJQ9NUn
**以太坊:**0xF055775eBD516e7419ae486C1d50C682d4170645

6. 技術交流

  • 區塊鏈技術交流QQ羣:348924182

  • 「區塊鏈部落」官方公衆號

發佈了94 篇原創文章 · 獲贊 31 · 訪問量 26萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章