hadesjaky / IPFSNotebook

IPFS学习笔记

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

IPFS学习笔记

版本:

  • 本文档持续更新......
  • 即将补充Bittorrent和Merkle DAG详细内容

参考:

PPT: PPT

IPFS简介

Protocol Labs协议实验室成立于2014年5月,由IPFS和Filecoin的发明者Juan Benet创立。在2014年夏天,加入了美国顶级孵化器Y-Combinator。协议实验室于2015年1月向世界发布了IPFS,从此,IPFS在各行业的组织中获得了巨大的发展。在2016年,IPFS一度成为区块链行业中最受青睐的技术之一,数千名开发人员称之为“WEB的未来”。同年,协议实验室还创建了libp2p、IPLD、multiformats、Orbit以及其他项目。而我们最期待的项目是Filecoin,目前正在开发中,预计在今年的晚些时候上线。

IPFSIPFS的中文名是星际文件系统(InterPlanetary File System),它本质上是一种内容可寻址、版本化、点对点超媒体的分布式存储、传输协议 ,目标是补充甚至取代过去20年里使用的超文本媒体传输协议(HTTP) ,希望构建更快、更安全、更自由的互联网时代.

为什么要取代HTTP?

  1. HTTP效率低下,服务器成本昂贵: 使用HTTP协议从一台计算机服务器上一次只能下载一个文件,而不是同时从多台计算机中获取文件。通过P2P方式的视频传输可以节省带宽成本的60%。
  1. 历史文件被删除: 网页的平均使用寿命为100天,大量的网站文件不能得以长期保存。有些重要的文件因操作不当,也有可能永远在互联网消失。
  1. 中心化的网络限制了机会 互联网一直是人类进步的催化器,但中心化的网络容易被控制,是对互联网良性发展的的威胁。
  1. 网络应用太依赖骨干网 为保证数据的可靠性,我们开发的应用程序太依赖大型的中心服务器,并通过大量的备份来保证数据的安全。

HTTP协议已经用了20年的历史,从HTTP 1.0 到现在的HTTP 5,网页的展示越来越美观丰富,但它背后的Browser/Server 模式是从来没变的。

对比HTTP,IPFS具有这样的一些特性:

  1. 基于内容寻址,而非基于域名寻址。文件(内容)具有存在的唯一性,一个文件加入了IPFS的网络,将基于计算对内容赋予一个唯一加密的哈希值。这将改变我们使用域名访问网络的习惯。

  2. 提供文件的历史版本控制器(如git),并且让多节点使用保存不同版本的文件。

  3. IPFS的网络上运行着一条区块链,即用来存储互联网文件的哈希值表,每次有网络访问,即要在链上查询该内容(文件)的地址。

  4. 通过使用代币(FileCoin)的激励作用,让各节点有动力去存储数据。 Filecoin 是一个由加密货币驱动的存储网络。矿工通过为网络提供开放的硬盘空间获得Filecoin,而用户则用 Filecoin 来支付在去中心化网络中储存加密文件的费用。

IPFS协议栈

IPFS至少有七层协议栈,从下至上分别为身份、网络、路由、交换、对象、文件、命名、应用(有些认为八层协议栈的存在应用层),每层协议栈各司其职,写成独立于上层,但上层依赖于下层。

各层解释:

  • 身份层和路由层可以一起解释。对等节点身份信息的生成以及路由规则是通过Kademlia协议生成制定,KAD协议实质是构建了一个分布式松散Hash表,简称DHT,每个加入这个DHT网络的人都要生成自己的身份信息(通过哈希生成的ID),然后才能通过这个身份信息去负责存储这个网络里的资源信息和其他成员的联系信息。

  • 网络层比较核心,使用的LibP2P可以支持任意传输层协议。NAT技术能让内网中的设备共用同一个外网IP,我们都体验过的家庭路由器就是这个原理。

  • 交换层,是类似迅雷这样的BT工具。

    1. 迅雷其实是模拟了P2P网络,并创建中心服务器,当服务器登记用户请求资源时,让请求同样资源的用户形成一个小集群swarm,在这里分享数据。这种方式有弊端,一位服务器是由迅雷统一维护,如果出现了故障、宕机时,下载操作无法进行。
    1. 中心化服务还可以限制一些下载请求,人们发明了一种更聪明的方式就是Bittorrent,让每一个种子节点所要存储的数据,通过哈希表存储在里面,BT工具相对不太受监管,服务更加稳定。
    1. IPFS团队把BitTorrent进行了创新,叫作Bitswap,它增加了信用和帐单体系来激励节点去分享,我推断FileCoin有很大概率是基于Bitswap,用户在Bitswap里增加数据会增加信用分,分享得越多信用分越高。如果用户只去检索数据而不存数据,信用分会越来越低,其它节点会在嵌入连接时优先选择信用分高的。这一设计可以解决女巫攻击,信用分不可能靠机器刷去提高,一直刷检索请求,信用分越刷越低。请求次数和存储量的变量之间有一个比较精妙的算法,类似一个抛物线,前期可以容忍很多东西,达到一定次数后不再信任。
  • 对象层和文件层适合结合来谈,它们管理的是IPFS上80%的数据结构,大部分数据对象都是以Merkle DAG的结构存在,这为内容寻址和去重提供了便利。文件层是一个新的数据结构,和DAG并列,采用Git一样的数据结构来支持版本快照。

  • 命名层具有自我验证的特性(当其他用户获取该对象时,使用指纹公钥进行验签,即验证所用的公钥是否与NodeId匹配,这验证了用户发布对象的真实性,同时也获取到了可变状态),并且加入了IPNS这个巧妙的设计来使得加密后的DAG对象名可定义,增强可阅读性。

  • 最后是应用层,IPFS核心价值就在于上面运行的应用程序,我们可以利用它类似CDN的功能,在成本很低的带宽下,去获得想要的数据,从而提升整个应用程序的效率。

新的技术取代老的技术,无非就两点:第一,能提高系统效率;第二,能够降低系统成本。IPFS把这两点都做到了。

技术拆解

本章将会将IPFS技术拆解,主要分成以下几部分进行解释:

  • Kademlia和DHT
  • Merkle Tree和Merkle DAG
  • Bittorrent和BitSwap
  • IPNS

1. Kademlia和DHT

DHT DHT全称叫分布式哈希表(Distributed Hash Table),是一种分布式存储方法,一类可由键值来唯一标示的信息按照某种约定/协议被分散地存储在多个节点上,这样也可以有效地避免“**集权式”的服务器的单一故障而带来的整个网络瘫痪。实现DHT的技术/算法有很多种,常用的有:Chord, Pastry, Kademlia等。我们这里要研究的是Kademlia算法。

  • DHT分布式哈希表: 1.哈希表被分割成不连续的块,每个节点被分配给一个属于自己的哈希块(称为区间表),并成为这个哈希块的管理者。 2.通过哈希函数,一个对象的名字或关键词被映射为128位或160位的散列值。

  • DHT网络的基本**: 1.每一份资源都由一组关键字进行标识。 2.系统对其中的每一个关键字进行Hash,根据Hash的结果决定此关键字对应的那条信息(即资源索引中的一项)由哪个用户负责储存。由此,生成哈希表。 3.用户搜索的时候,用同样的算法计算每个关键字的Hash,然后从哈希表获得该关键字对应的信息存储位置(具体查看关键字定位),并迅速定位资源。

  • DHT关键字定位 1.DHT通过分布式散列函数,将输入的关键字唯一映射到某个节点上,然后通过某些路由算法同该节点建立连接。 2.每个节点并不需要保存整个系统的节点视图信息,只在节点中存储其邻近的几个后继节点信息。当一个节点收到一个查询操作时,如果它发现所查询的标识不在自己关联的区间内,那么该节点将会把该查询发送给其存储节点信息表中它认为最靠近目标的邻居。 3.每次转发都能更进一步地接近数据源。因此较少的路由信息就可以有效地实现到达目标节点。

Kademlia 各种DHT的实现算法,不论是Chord, Pastry,还是Kademlia,其最直接的目标就是以最快的速度来定位到期望的节点,在P2P文件分享应用中则是以最快的速度来查找到正在分享某一文件/种子的peers列表信息。因为每个节点都是分布式存在于地球的任何角落,如果用地理距离来衡量两节点间的距离则可能给计算带来极大复杂性甚至不可能进行衡量,因此基本所有的DHT算法都是采用某种逻辑上的距离,在Kademlia则采用简单的异或计算 来衡量两节点间的距离,它和地理上的距离没有任何关系,但却具备几何公式的绝大特征:

  1. 节点和它本身之间的异或距离是0
  2. 异或距离是对称的:即从A到B的异或距离与从B到A的异或距离是等同的
  3. 异或距离符合三角形不等式:给定三个顶点A B C,假如AC之间的异或距离最大,那么AC之间的异或距离必小于或等于AB异或距离和BC异或距离之和.
  4. 对于给定的一个距离,距离A只存在有唯一的一个节点B,也即单向性,在查找路径上也是单向的,这个和地理距离不同。

Kademlia中规定所有的节点都具有一个节点ID,该节点ID的产生方法和种子文件中的info hash采用相同算法:即sha-1(安全hash算法)。因此每个节点的id,以及每个共享文件/种子的info-hash都是唯一的,并且都是20个字符160bits位组成。两个节点间的距离就是两个节点id的异或结果,节点离键值(种子)的距离为该节点的id和该种子文件的info-hash的异或结果。

Kademlia在异或距离度量的基础上又把整个DHT网络拓扑组织成一个二叉前缀树,所有的节点(所有的正在运行的,并且开取了DHT功能)作为该二叉前缀树的叶子节点,可以想象这棵二叉树可以容纳多达2128个叶子(节点),这足以组织任何规模的网络了。对于每个节点来说按照离自己的远近区域又可以把这棵树划分为160棵子树,每一个子树和该节点都有一个共同的前缀,共同前缀越少离得越远(异或结果亦是如此)。

例如:以下5个节点将会根据其ID组织成二叉树(模拟)

为了快速到达这160棵子树,处于DHT网络的每一个节点都记录了每棵子树上的K个节点的信息(ip,port,id),在BT中K固定为8。这份记录信息称为K桶,也叫路由表。这个路由表与通常IP路由的概念不一样,它代表了到达处于自己某个距离范围[2i—2i+1)的节点,可以通过该范围所选取的K个节点来定位。下图是路由表的结构:

实际上,路由表可能没有160份,因为路由表是对半拆分的,最初只有一份,在插入过程中,该路由表的节点大于k(8)时,则拆分成两半,一半包含自身节点,一半不包含自身节点,循环往复。(?路由表的节点大于k(8)?怎么拆分?) 每一个新加入DHT网络的节点,其路由表是空的,通过以下方式逐步形成自己的路由表:

  1. 非首次启动,从曾经保存过的路由表文件中直接读取;
  2. 首次启动,从超级节点中读取;
  3. 首次启动,没有超级节点,则在download文件的郭晨各种逐步形成;
  4. 动态刷新,每次上传/下载都按照一定规则建立/刷新路由表。

实际上,DHT是把Tracker集中维护的所有种子的peers-list信息利用DHT的方法散列并保存到所有的DHT网络中的节点上去,然后在此基础上提供查找的方法。在DHT中实现了两种类型的查找,一种是查找node(find_node),另一种是查找peers(get_peers)。 查找node过程如下:

  1. 如果节点x需要查找节点y,则x计算xor(x,y)并从本地K桶中得到k个比较closer的节点;
  2. 然后向这些比较close的k个节点继续询问它是否有离y更近的节点,这些k个节点当然也从自己的对应的K桶中返回k个更近的节点给x;
  3. x然后再从返回结果中选取k个more closer节点重复上面的动作,直到不能返回更近的节点为止,则最后找到的k个节点即为the most closest nodes;
  4. 在这个过程中返回的任何k个close的节点都会尝试去插到自己的路由表中去。

查找peers过程如下:而x查找peers-list的方法则和上面查找节点的方法类似,不同的是它是以info-hash作为参数进行查找,并且如果在查找过程中有任何一个节点返回了(info-hash, peers-list)对则提前结束查找。

当一个节点通过上面方法得到了peers-list后,则会试图对每个peers主动发起TCP的连接继续后面真实的下载过程,同时会把自己的peer信息发送给先前的告诉者和自己K桶中的k个最近的节点存储该peer-list信息。该信息在该k个节点上可以保存24个小时,24小时后如果没有收到x发送的更新消息则失效。因此,一个活动节点是存储了两部分信息:一份是本地的路由表,另一份是<info-hash,peer-list>列表信息(有多个)。

2.Merkle Tree和Merkle DAG

Merkle Tree Merkle Tree,通常也被称作Hash Tree,顾名思义,就是存储hash值的一棵树。Merkle树的叶子是数据块(例如,文件或者文件的集合)的hash值。非叶节点是其对应子节点串联字符串的hash。

  • 哈希算法(Hash)又称哈希函数、散列技术、摘要。
  • 哈希算法是可以将任意长度的数据映射成固定长度的数据的函数,对一份数据进行哈希运算的结果一般都是唯一的
  • 只要原文发生改变,哈希运算的结果就会完全不一样。
  • 哈希逆运算在数学上是不可能的。
  • 主要用于数字签名、错误检验等场景。
  • 哈希碰撞:对不同的数据进行哈希运算产生相同的结果。概率极小
  • 常见的hash算法有MD5以及SHA系列。

在稳定服务器的场景中,从服务器下载数据后,采用单一的哈希进行检验。如果哈希结果不正确,说明数据在传输过程中发生错误。此时,需要重新下载整份数据,这是方法的效率是很低的。 在在点对点网络的场景中,由于节点机器被认为是不稳定或不可信的,为了校验数据的完整性,更好的办法就是将大份数据分割成许多小的数据块来保存和传输。这样做的好处就是,当数据出错时,只需要对错误的数据进行重传。 第一种方法就是Hash List:

点对点下载的时候,在真正地下载数据之前,会先下载一个Hash列表,该Hash列表就是各个数据块的Hash值。然后从可信的服务器获取根hash(就是图中的top hash),用根hash来校验hash列表。校验过程是:将Hash列表的所有hash按顺序结成字符串,再做一次Hash运算,结果与根Hash对比。 第二种方法就是Merkle Tree, 跟Hash List一样,Merkle Tree先计算小数据块的hash值,然后按顺序将相邻的hash合并成字符串,再计算该字符串的hash,逐级计算,最终得出树根Merkle Root。

点对点下载的时候,从可信源获取Merkle Root,从不可信源获取Merkle Tree,这样就这一检验数据是否有错误。与Hash List不同的是,Merkle Tree可以直接下载并立即检验树的一个分支:如果数据块错误,需要下载完整的Hash List来验证,而Merkle tree只需要下载一个分支并立即验证,不同在下载另一个分支,以此类推。

Merkle Tree的特点:

  1. MT是一种树,大多数是二叉树,它具有树结构所有的特点;
  2. MT的叶子节点的值可以是小数据块的hash或小数据块;
  3. 非叶子节点的值都是其子节点值的hash结果。

详细的Merkle Tree算法解析请点击

Merkle DAG Merkle DAG的全称是 Merkle directed acyclic graph(默克有向无环图),它是在Merkle tree基础上构建的。Merkle DAG跟Merkle tree很相似,区别在于:Merkle DAG不需要进行树的平衡操作,非叶子节点允许包含数据等。 IPFS的Merkle DAG是由Git改造而来的,定义了一组对象:

  • Blob-一个大小可变的数据块(等于或小于256KB)。Blob对象代表一个文件且包含一个可寻址的数据单元,用来存储用户的数据。Blob没有links。
  • List-块或者其他链表的集合。List对象代表着由几个blob对象连接而成的大文件或者重复数据删除文件。List中包含有序的blob序列或者其他list 对象。
  • Tree-块、链表或者而其他树的集合。Tree代表一个目录,一个名字到哈希值的映射。哈希值则代表了bolbs、lists和其他trees。
  • Commit-任何对象在版本历史记录中的一个快照。他同样连接着父提交。

Merkle DAG拥有如下的功能:

  • 内容寻址:使用多重哈希来唯一识别一个数据块的内容
  • 防篡改:可以方便的检查哈希值来确认数据是否被篡改
  • 去重:由于内容相同的数据块哈希是相同的,可以很容去掉重复的数据,节省存储空间

详细的Git命令解释请点击

3.Bittorrent和BitSwap

点对点的数据传输

  • 数据不是存储在中心化的服务器,而是存储在各个节点上。
  • 节点是对等的,节点即是客户端,又充当服务器的角色。

Bittorrent 特点:

  • 一种点对点传输的网络协议。
  • 对于一个文件,下载的用户数越大,下载速度就越快。
  • 部分的网络拥堵或服务器宕机并不会对整个传输链路造成太大的影响。
  • 常见的BT软件有:迅雷、QQ旋风、比特精灵等。

存在问题:

  • 节点只索取不贡献,导致数据交换的效率极速下降,甚至点对点网络瘫痪。
  • 容易遭受女巫攻击,即恶意机器不断请求,占用本机上传带宽。

BitSwap IPFS在BitTorrent的基础上实现了p2p数据交换协议:BitSwap协议。 IPFS每一个节点都维护了两个列表:

  • 已有的数据块(have_list)
  • 想要的数据块(want_list)

当两个节点建立连接后,他们会根据hava_list和want_list互通有无。跟BitTorrent不一样的是:BitSwap获取数据块的时候不限于从同一个torrent里面。也就是说BitSwap可以从不属于本文件的其他文件获取数据块(只要数据块的哈希值一样,数据内容必然是一样的,同样的数据块只会保留一份)。从全局考虑,这使得BitSwap的效率相比于BitTorrent更高。 对于p2p网络,有一个很重要的问题是:如何激励大家分享自己的数据?IPFS实现了自己的特殊的数据分享策略。IPFS的策略体系由信用、策略、账单组成。 后期将会使用filecoin来实现激励策略

信用体系:BitSwap协议必须能够激励节点去乐于分享数据,即使这个节点暂时没有数据需求。IPFS根据节点的之间的数据收发建立了一个信用体系:发送给其他节点数据可以增加信用值;从其他节点接受数据降低信用值。如果一个节点只接收数据而不分享数据,信用值就会降得很低而被其他节点忽略掉。 简单来讲就是:你乐于分享数据,其它节点也乐于发送数据给你,如果你不愿意分享,那么其它节点也不愿意给你数据。

账单:BitSwap节点会记录下来和其他节点通信的账单(数据收发),可以保持节点间数据交换的历史和防止篡改。当两个节点之间建立连接的时候,BitSwap会相互交换账单信息,如果账单不匹配,则清除重新记账。恶意节点可能会故意“丢失”账单,以希望清除掉自己的债务。其它交互节点会把这些都记下来,如果总是发生故意“丢失”账单的情况,该节点就会被拒绝。

实现策略:根据上面的信用体系,BitSwap可以采取不同的策略来实现,每一种策略都会对系统的整体性能产生不同的影响。策略的目标是:

  • 节点数据交换的整体性能和效率最高;
  • 阻止“吃白食”(freeloaders)的现象,即就是不能够只下载数据不上传数据;
  • 可以有效的防止一些攻击行为(比如:女巫攻击)
  • 对信任节点建立宽松机制(lenient)

IPFS提供一个可参考的策略机制(实际的实现可以有所变化)

4.IPNS

到目前为止,IPFS堆栈形成了构建内容寻址对象 DAG 的P2P交换。它可以用于发布和检索不可变的对象,甚至可以跟踪这些对象的版本历史。但是,仍缺少一个关键组件:可变命名。没有它,用户就得在IPFS系统外获取到新的内容地址了。

自验证命名 1.将节点公钥的哈希结果定义节点的NodeId; 2.通过 /ipns/NodeId的方式可以访问该节点下的内容; 3.当其他节点从该节点获取文件时,可以先验证其公钥和NodeId是否匹配,以到达文件对象的真实性。 通过自验证命名,我们可以实现这样的访问效果/ipns//docs/test.md而不必用/ipfs/<test.md’s Hash>这样的方式、

场景模拟

  1. 加入IPFS网络,在网络中搜索叫ABC的文件(通过IPNS——去中心化的文件命名系统)

  2. IPFS网络迅速索引区块链上的哈希值,反馈出搜索结果。

  3. 你支付一点FileCoin代币, 获取ABC文件缓存到本地,ABC文件不是从云或者服务器上下载下来的,而是由这个网络的参与者贡献的,它可能是离你最近的一个网络节点。这样的好处就是不仅不需要中间服务器,而且网络效率最快。

  4. 如果ABC文件恰好你周边好几个人都有,那IPFS网络会把这个文件拆成一小片一小片,节省了这些节点的储存成本,也让你用最具效率的方式下载到该视频。

  5. 这个视频文件缓存在自己电脑里,不仅自己观看,同时也为其他人提供资源。

  6. 另外也可以自己发布新内容到这个网络上,并且有机会获得FileCoin代币,因为你也为网络做了贡献。

About

IPFS学习笔记