深入了解IPFS(2/6):什么是星际关联数据(IPLD)?

2019-04-08 14:11:49

  这篇文章是“深入理解IPFS”系列文章的续篇(第2部分),它将帮助理解IPFS的基本概念,如果你想了解什么是IPFS及其工作原理,那么你应该查阅第一篇。

  在本系列文章的第一部分中,我们简要讨论了IPLD。我们看到IPLD处理IPFS中的“定义数据”。在这一部分中,我们将深入研究IPLD并进行讨论:

  IPLD的意义它背后的哲学是什么,我们为什么需要它以及它为什么适合IPFS?

  IPLD是如何工作的说明IPLD的工作原理,以及它是如何与IPFS的其他组件协调的?

  实际使用实际操作的过程总是有趣的。

  希望你可以从本系列中学到很多关于IPFS的知识。让我们开始吧!


  第一、IPLD的重要性

  IPLD不仅是IPFS项目的一部分,而且是一个单独的项目。要理解它在去中心化世界中的重要性,我们必须理解关联数据的概念:语义性网络。


  什么是关联数据?为什么我们需要它

  语义性网络(Semantic Web)或关联数据(Linked Data)是蒂姆•伯纳斯•李爵士(Sir Tim Berners Lee)于2001年发表在《科学美国人》上的一篇开创性文章中创造的一个术语。伯纳斯•李在文章中阐述了万维网的愿景,即机器可以独立于人类处理数据,从而实现一系列改变我们日常生活的新服务。数据可以由软件代理进行分析和操作,然而,这篇论文对大多数包含结构化数据的网络页面设想还并没有实现,随着越来越多的社区使用国际语义网络标准(称为链接数据)实现数据共享,语义性网络已经成为一个对数据交换和集成越来越重要的平台。

  目前有许多使用语义性网络技术和链接数据的例子,它们以灵活和可扩展的方式在网络上共享有价值的信息。语义性网络的相关技术被广泛应用于生命科学中,通过在多个数据集之间寻找路径来促进新药物的发现,而这些数据集通过与每个数据集相关的基因来显示药物和副作用之间的关联。《纽约时报》公布了其150多年来发展起来的约10,000个主题或标题的词汇来作为链接数据,并将其覆盖面扩大到约30,000个主题标签;它们鼓励开发使用这些词汇表的服务,并将它们与其他在线资源连接起来。英国广播公司则通过使用链接数据,使内容更容易被搜索引擎找到,也更容易通过社交媒体链接进行传播;从音乐或体育等领域使用补充资源并添加额外的内容,进行链接的传播,使其超出最初的输入目标,以便在附加上下文中提供相关信息。美国data.gov网站的主页上说:“随着链接文档的网络发展到包括链接数据网络,我们正在努力最大限度地发挥语义性网络技术的潜力,以实现链接数据的公开。”而且目前所有的社交媒体网站都在使用链接数据来创建网络,以此使他们的平台尽可能地吸引人。

  的确,我们目前有一些关联数据正在被使用,但要利用关联数据的真正力量,我们还有很长的路要走。

  想象一下,如果你可以将你在git分支中的最新提交引用到比特币交易中来为你的工作添加时间戳。通过链接git的提交,你可以从区块链资源管理器中查看提交。或者,如果你可将以太坊合约链接到IPFS上,那样就可以修改它,并在每次函数执行时跟踪它的更改。

  所有这些都是可以使用IPLD实现的。

  IPLD是基于内容可寻址网络的数据模型(如第1部分所述)。

  它允许我们将所有哈希链接的数据结构视为统一子集,将所有数据与链接的数据模型统一为IPLD的实例。

  换句话说,IPLD是一组用于创建去中心化数据结构的标准,这些数据结构具有普遍的可寻址性和可链接性。这些结构允许我们处理数据,就像url和链接处理HTML 网络页面一样。

  通过哈希进行内容寻址已经成为分布式系统中连接数据的一种广泛使用方法,从在区块链上运行你最喜欢的加密货币到代码的提交,再到网络内容。然而,尽管所有这些工具都依赖于一些公共原则,但它们特定的底层数据结构是不可互操作的(目前我无法将git提交链接到区块链上)。

  IPLD是所有哈希启发协议的单一名称。通过IPLD,链接是可以跨协议的,无论底层协议如何,都可以探索数据。


  第二、IPLD是如何工作的

  在深入研究IPLD之前,让我们先看看IPLD的属性。

  1、IPLD的属性

  由于IPLD允许跨协议工作,所以我认为它是前途无量的。关键是IPLD提供了一些库,而这些库使底层数据在默认情况下可以跨工具和跨协议进行交互操作。

  2、规范数据模型

  一个独立的描述模型,它可以标识任何基于哈希的数据结构,并确保相同的逻辑对象总是映射到完全相同的序列。

  3、协议独立解决方案

  IPLD将孤立的系统集成在一起(如连接比特币、以太坊和git),使与现有协议的集成变得简单。

  4、可升级

  有了Multiformats(我们将在第4部分中深入讨论)的支持,IPLD将很容易升级,并且内容会根据你喜欢的协议而进行增加。

  5、跨格式操作

  用各种可序列化的格式(如JSON、CBOR、YAML、XML等)表示IPLD对象,使IPLD可以轻松地与任何框架一起进行使用。

  6、向下兼容性

  非侵入性的解析器使IPLD更加易于集成到现有的工作中。

  7、所有协议的命名空间

  IPLD允许你无缝地跨协议探索数据,通过公共的命名将基于哈希的数据结构绑定在一起。

  现在,让我们更深入地研究IPLD。


  第三、深入了解IPLD规范

  要知道,IPLD不是一个单一的规范,而是一组规范。


   1.png   

  IPLD堆栈图


  这个堆栈的目的是启用分散的数据结构,而分散的数据结构反过来又将启用更加分散的应用程序。


  所以,这个堆栈中的许多规范是相互依赖的。


 2.png

  IPLD 依赖图


  这些图显示了IPLD的高级项目规范。即使你不完全理解,也没关系。

  要了解有关IPLD的更多信息,请参阅Juan Benet的精彩演讲。

  好的,理论的东西已经够多了。让我们来看看这篇文章最有趣的部分


  第四、对于IPLD的实际操作

  在IPFS中,IPLD有助于构造和链接所有数据块/对象。所以,正如我们在第1部分中看到的,IPLD负责组织的所有数据块以构成了小猫的形象。

  在本部分中,我们将创建一个类似于medium.com的发布系统,并使用IPLD链接标签、文章和作者。这将帮助你更直观地理解IPLD,你也可以在Github上找到完整的教程。

  让我们开始吧!

  在创建发布系统之前,我们将研究IPFS DAG API,它允许我们以IPLD格式存储IPFS中的数据对象。(你可以在IPFS中存储更多令人兴奋的东西,比如你最喜欢的猫的图像,但我们暂时只存储些简单的东西。)

  如果你不熟悉Merkle和DAGs,那么请到这里来。如果你理解了这些术语的意思,那么继续……

  创建一个名为ipld-blogs的文件夹。运行npm init并按回车键查看所有问题。

  现在安装依赖使用:

  npm install ipfs-http-client cids --save

  安装模块后,你的项目结构将如下图所示:


3.png


  创建IPLD格式节点


  你可以通过将数据对象传递到ipfs.dag来创建一个新节点,该方法为新创建的节点回报内容标识符(CID)。

  ipfs.dag.put({name: ‘vasa’})

  CID是IPFS中的一个数据块的地址,该数据块由其内容派生而来。每当有人将相同的{name: 'vasa'}数据放入IPFS时,他们将得到与你得到的相同的CID。如果他们输入{name: 'vAsa'}, CID将会不同。

  将此代码粘贴到tut.js中并运行node .js

  //Initiate ipfs and CID instance

  const ipfsClient = require('ipfs-http-client');

  const CID = require('cids');

  //Connecting ipfs instance to infura node. You can also use your local node.

  const ipfs = new ipfsClient({ host: 'ipfs.infura.io', port: '5001', protocol: 'https' });

  /*

  Creating an IPLD format node:

  ipfs.dag.put(dagNode, [options], [callback])

  For more information see:

  https://github.com/ipfs/interface-js-ipfs-core/blob/master/SPEC/DAG.md#ipfsdagputdagnode-options-callback

  */

  ipfs.dag.put({name: "vasa"}, { format: 'dag-cbor', hashAlg: 'sha2-256' }, (err, cid)=>{

  if(err){

  console.log("ERR\n", err);

  }

  //featching multihash buffer from cid object.

  const multihash = cid.multihash;

  //passing multihash buffer to CID object to convert multihash to a readable format

  const cids = new CID(1, 'dag-cbor', multihash);

  //Printing out the cid in a readable format

  console.log(cids.toBaseEncodedString());

  //zdpuAujL3noEMamveLPQWJPY6CYZHhHoskYQaZBvRbAfVwR8S

  });

  你将得到一个CID “zdpuaujl3 noemamvelpqwjpy6cyzhhhoskyqazbvrbafvwr8”。至此,我们已经成功创建了一个IPLD格式节点。

  连接IPLD对象

  有向无环图(DAGs)其中的一个重要特征是能够将它们链接在一起。

  在ipfs DAG存储中表示链接的方式是使用另一个节点的CID。

  例如,如果我们想让一个节点有一个名为“foo”的链接,指向另一个以前保存为barCid的CID实例,它有可能看起来是这样的:

  {

  Foo: barCid

  }

  当我们为一个字段指定一个名称并将其值作为到CID的链接时,我们将其称为已命名链接。

  下面的这段代码显示了如何创建一个命名链接。

  //Initiate ipfs and CID instance

  const ipfsClient = require('ipfs-http-client');

  const CID = require('cids');

  //Connecting ipfs instance to infura node. You can also use your local node.

  const ipfs = new ipfsClient({ host: 'ipfs.infura.io', port: '5001', protocol: 'https' });

  /*

  Creating an IPLD format node:

  ipfs.dag.put(dagNode, [options], [callback])

  For more information see:

  https://github.com/ipfs/interface-js-ipfs-core/blob/master/SPEC/DAG.md#ipfsdagputdagnode-options-callback

  */

  async function linkNodes(){

  let vasa = await ipfs.dag.put({name: 'vasa'});

  //Linking secondNode to vasa using named link.

  let secondNode = await ipfs.dag.put({linkToVasa: vasa});

  }

  linkNodes();

  使用链接读取嵌套数据

  你可以使用路径从深层嵌套对象中读取数据并查询。

  ipfs.dag.get允许使用IPFS路径进行查询。这些查询将回报一个对象,该对象包含查询的值和任何未解析的剩余路径。

  这个API很酷的一点是,它还可以遍历链接。下面是如何使用链接读取嵌套数据的示例。

  //Initiate ipfs and CID instance

  const ipfsClient = require('ipfs-http-client');

  const CID = require('cids');

  //Connecting ipfs instance to infura node. You can also use your local node.

  const ipfs = new ipfsClient({ host: 'ipfs.infura.io', port: '5001', protocol: 'https' });

  function errOrLog(err, result) {

  if (err) {

  console.error('error: ' + err)

  } else {

  console.log(result)

  }

  }

  async function createAndFeatchNodes(){

  let vasa = await ipfs.dag.put({name: 'vasa'});

  //Linking secondNode to vasa using named link.

  let secondNode = await ipfs.dag.put({

  publication: {

  authors: {

  authorName: vasa

  }

  }

  });

  //featching multihash buffer from cid object.

  const multihash = secondNode.multihash;

  //passing multihash buffer to CID object to convert multihash to a readable format

  const cids = new CID(1, 'dag-cbor', multihash);

  //Featching the value using links

  ipfs.dag.get(cids.toBaseEncodedString()+'/publication/authors/authorName/name', errOrLog);

  /* prints { value: 'vasa', remainderPath: '' } */

  }

  createAndFeatchNodes();

  你还可以使用这个很酷的IPLD资源管理器来探索你的IPLD节点。比如,如果我想看CID zdpuAujL3noEMamveLPQWJPY6CYZHhHoskYQaZBvRbAfVwR8S

  我将会打开这个链接 :https://explore.ipld.io/#/explore/zdpuAujL3noEMamveLPQWJPY6CYZHhHoskYQaZBvRbAfVwR8S

  现在,由于我们已经研究了IPFS DAG API,我们准备使用IPLD创建我们的发布系统。

  创建发布系统

  我们将创建一个简单的博客应用程序。 这个博客应用程序可以:

  · 添加一个新的Author IPLD对象。作者将有两个字段:name和profile(你的profile的标记行)。

  · 创建一个新的Post IPLD对象。帖子将包含4个字段:作者,内容,标签和发布日期时间。

  · 使用帖子CID来阅读帖子。

  以下是上述目标的代码实现:

  /*

  PUBLICATION SYSTEM

  Adding new Author

  An author will have

  -> name

  -> profile

  Creating A Blog

  A Blog will have a:

  -> author

  -> content

  -> tags

  -> timeOfPublish

  List all Blogs for an author

  Read a Blog

  */

  //Initiate ipfs and CID instance

  const ipfsClient = require('ipfs-http-client');

  const CID = require('cids');

  //Connecting ipfs instance to infura node. You can also use your local node.

  const ipfs = new ipfsClient({ host: 'ipfs.infura.io', port: '5001', protocol: 'https' });

  //Create an Author

  async function addNewAuthor(name) {

  //creating blog object

  var newAuthor = await ipfs.dag.put({

  name: name,

  profile: "Entrepreneur | Co-founder/Developer @TowardsBlockChain, an MIT CIC incubated startup | Speaker | https://vaibhavsaini.com"

  });

  //Fetching multihash buffer from cid object.

  const multihash = newAuthor.multihash;

  //passing multihash buffer to CID object to convert multihash to a readable format

  const cids = new CID(1, 'dag-cbor', multihash);

  console.log("Added new Author "+name+": "+cids.toBaseEncodedString());

  return cids.toBaseEncodedString();

  }

  //Creating a Blog

  async function createBlog(author, content, tags) {

  //creating blog object

  var post = await ipfs.dag.put({

  author: author,

  content: content,

  tags: tags,

  timeOfPublish: Date()

  });

  //Fetching multihash buffer from cid object.

  const multihash = post.multihash;

  //passing multihash buffer to CID object to convert multihash to a readable format

  const cids = new CID(1, 'dag-cbor', multihash);

  console.log("Published a new Post by "+author+": "+cids.toBaseEncodedString());

  return cids.toBaseEncodedString();

  }

  //Read a blog

  async function readBlog(postCID){

  ipfs.dag.get(postCID,(err, result)=>{

  if (err) {

  console.error('Error while reading post: ' + err)

  } else {

  console.log("Post Details\n", result);

  return result;

  }

  });

  }

  function startPublication(){

  addNewAuthor("vasa").then((newAuthor)=>{

  createBlog(newAuthor,"my first post", ["ipfs","ipld","vasa","towardsblockchain"]).then((postCID)=>{

  readBlog(postCID);

  })

  });

  }

  startPublication();

  在运行此代码时,它将首先通过addNewAuthor来创建一个作者,该作者将返回作者的CID。然后将此CID传递给createBlog函数,然后该函数返回postCID。readBlog函数将使用此postCID来获取帖子的详细信息。

  你还可以使用IPLD来创建更复杂的应用程序...

  好的,这部分就讲到这里。如果你有任何问题,可以在评论中提出。

  我希望你可以从这篇文章中学到很多东西。在下一篇文章中,我们将深入探讨分布式Web的命名系统IPNS。敬请期待...

  感谢protoschool对于DAGs的出色解读

  感谢你的阅读。





最新推荐