IPLD数据模型定义了一种简单的,适用于所有merkle-dags,基于JSON的结构。同时也定义了一系列编码的格式结构。
有如下限制:
如下特性是加分项:
(住: 此处同时使用JSON和 YML来展示格式的形式。我们使用两者来显示两种不同格式的对象的等价性。)
IPLD 数据模型的核心仅仅是JSON,也就是说它 (a) 是树状结构的文件,有一些原始类型,(b) 与JSON实现一对一映射 © 可以在json中使用它
另一方面,它又不是“JSON”因为 (a)它纠正了一些错误, (b)实现了高效序列化 , 同时 ©并不局限于单一的传输格式,有待于新的技术
下面是一个用JSON表示的IPLD对象 :
{
"name": "Vannevar Bush"
}
假设它的multihash值为QmAAA...AAA
。 注意到其中没有链接,只有字符串。但是用户仍可以通过keyname
来解析它。
> ipld cat --json QmAAA...AAA
{
"name": "Vannevar Bush"
}
> ipld cat --json QmAAA...AAA/name
"Vannevar Bush"
同时,在yml结构中:
> ipld cat --yml QmAAA...AAA
---
name: Vannevar Bush
> ipld cat --xml QmAAA...AAA
<!xml> <!-- todo -->
<node>
<name>Vannevar Bush</name>
</node>
节点间的Merkle-Link是IPLD存在的原因。IPLD 内的Link只是节点内部包含的特殊格式:
{
"title": "As We May Think",
"author": {
"/": "QmAAA...AAA" // 链接到上个例子的数据
}
}
假设以上数据的 multihash值为QmBBB...BBB
。 该节点有_subpath链接author
到QmAAA...AAA
,所以可以有如下操作:
> ipld cat --json QmBBB...BBB
{
"title": "As We May Think",
"author": {
"/": "QmAAA...AAA" // links to the node above.
}
}
> ipld cat --json QmBBB...BBB/author
{
"name": "Vannevar Bush"
}
> ipld cat --yml QmBBB...BBB/author
---
name: "Vannevar Bush"
> ipld cat --json QmBBB...BBB/author/name
"Vannevar Bush"
通过使用链接,IPLD的用户可以构建复杂的数据结构。这样可以方便的将信息编码,例如表示一种关系结构,或者添加辅助数据。但是它不同于接下来要讨论的“对象链接约定”。有时候,你只是想在链接上添加一些数据,而不必制作另一个对象。 IPLD不会妨碍你。 您可以简单地通过将实际的IPLD链接嵌套在另一个对象中,并使用附加属性来完成。
请注意: 链接属性不允许直接在链接对象,因为travesal歧义。 阅读spec历史记录,就实现困难的讨论。
例如,假设你有一个文件系统,并且想分发权限控制的元信息,或者节点间的归属权。假设你有一个目录对象 directory
它的哈希值为QmCCC...CCC
:
{
"foo": { // link wrapper with more properties
"link": {"/": "QmCCC...111"} // the link
"mode": "0755",
"owner": "jbenet"
},
"cat.jpg": {
"link": {"/": "QmCCC...222"},
"mode": "0644",
"owner": "jbenet"
},
"doge.jpg": {
"link": {"/": "QmCCC...333"},
"mode": "0644",
"owner": "jbenet"
}
}
用 YML表示:
---
foo:
link:
/: QmCCC...111
mode: 0755
owner: jbenet
cat.jpg:
link:
/: QmCCC...222
mode: 0644
owner: jbenet
doge.jpg:
link:
/: QmCCC...333
mode: 0644
owner: jbenet
即使我们在数据结构中增加了特有属性的描述,仍然可以解析:
> ipld cat --json QmCCC...CCC/cat.jpg
{
"data": "\u0008\u0002\u0012��\u0008����\u0000\u0010JFIF\u0000\u0001\u0001\u0001\u0000H\u0000H..."
}
> ipld cat --json QmCCC...CCC/doge.jpg
{
"subfiles": [
{
"/": "QmPHPs1P3JaWi53q5qqiNauPhiTqa3S1mbszcVPHKGNWRh"
},
{
"/": "QmPCuqUTNb21VDqtp5b8VsNzKEMtUsZCCVsEUBrjhERRSR"
},
{
"/": "QmS7zrNSHEt5GpcaKrwdbnv1nckBreUxWnLaV4qivjaNr3"
}
]
}
> ipld cat --yml QmCCC...CCC/doge.jpg
---
subfiles:
- /: QmPHPs1P3JaWi53q5qqiNauPhiTqa3S1mbszcVPHKGNWRh
- /: QmPCuqUTNb21VDqtp5b8VsNzKEMtUsZCCVsEUBrjhERRSR
- /: QmS7zrNSHEt5GpcaKrwdbnv1nckBreUxWnLaV4qivjaNr3
> ipld cat --json QmCCC...CCC/doge.jpg/subfiles/1/
{
"data": "\u0008\u0002\u0012��\u0008����\u0000\u0010JFIF\u0000\u0001\u0001\u0001\u0000H\u0000H..."
}
但是link的解析仍需要通过遍历获得。
值得注意的是目前不允许有重名的属性,即使这样通过parsers也可能会出现这样的问题。所以,为了避免冲突,解析时只读取第一个出现的条目。例如,有如下对象:
{
"name": "J.C.R. Licklider",
"name": "Hans Moravec"
}
以这样的顺序出现在在标准格式中 Canonical Format (不是 json, 是 cbor), 它的哈希值为 QmDDD...DDD
。 我们只能得到:
> ipld cat --json QmDDD...DDD
{
"name": "J.C.R. Licklider",
"name": "Hans Moravec"
}
> ipld cat --json QmDDD...DDD/name
"J.C.R. Licklider"
Unix和Web中的路径描述有一些重要的问题。 具体请看这个讨论this discussion。 为了与unix和web的模型和期望兼容,IPLD明确地禁止具有特定路径组件的路径。 请注意,数据本身可能仍然包含这些属性(有人会这样做,并有合法的用途)。 所以只有路径解析器不能通过这些路径来解析。 这些限制与典型的unix和UTF-8路径系统相同:
IPLD与JSON直接兼容,可以充分利用JSON的成功,但是不用被JSON的错误所束缚。 这是我们能够遵循格式惯用选择的地方,但必须注意确保始终存在定义明确的1:1映射。 关于整数,在JSON中有多种表示整数的字符串,例如EJSON。 这些可以被使用,并且从其他格式的转换应该自然地发生 — 也就是说,当将JSON转换为CBOR时,EJSON整数应该自然地转换为适当的CBOR整数,而不是将其表示为具有字符串值的映射。
PLD是一种简单,灵活和灵活的格式,不妨碍用户定义新的或导入的旧数据文件,这一点很重要。 为此,下面我将展示一些示例数据结构。
Unix 文件系统
A small File 一个小文件
{
"data": "hello world",
"size": "11"
}
A Chunked File 文件的一部分 将文件分解
{
"size": "1424119",
"subfiles": [
{
"link": {"/": "QmAAA..."},
"size": "100324"
},
{
"link": {"/": "QmAA1..."},
"size": "120345",
"repeat": "10"
},
{
"link": {"/": "QmAA1..."},
"size": "120345"
},
]
}
A Directory 一个目录
{
"foo": {
"link": {"/": "QmCCC...111"},
"mode": "0755",
"owner": "jbenet"
},
"cat.jpg": {
"link": {"/": "QmCCC...222"},
"mode": "0644",
"owner": "jbenet"
},
"doge.jpg": {
"link": {"/": "QmCCC...333"},
"mode": "0644",
"owner": "jbenet"
}
}
git git blob 数据块
{
"data": "hello world"
}
git tree 树状结构
{
"foo": {
"link": {"/": "QmCCC...111"},
"mode": "0755"
},
"cat.jpg": {
"link": {"/": "QmCCC...222"},
"mode": "0644"
},
"doge.jpg": {
"link": {"/": "QmCCC...333"},
"mode": "0644"
}
}
git commit 提交信息
{
"tree": {"/": "e4647147e940e2fab134e7f3d8a40c2022cb36f3"},
"parents": [
{"/": "b7d3ead1d80086940409206f5bd1a7a858ab6c95"},
{"/": "ba8fbf7bc07818fa2892bd1a302081214b452afb"}
],
"author": {
"name": "Juan Batiz-Benet",
"email": "juan@benet.ai",
"time": "1435398707 -0700"
},
"committer": {
"name": "Juan Batiz-Benet",
"email": "juan@benet.ai",
"time": "1435398707 -0700"
},
"message": "Merge pull request #7 from ipfs/iprs\n\n(WIP) records + merkledag specs"
}
Bitcoin 比特币 Bitcoin Block 比特币区块
{
"parent": {"/": "Qm000000002CPGAzmfdYPghgrFtYFB6pf1BqMvqfiPDam8"},
"transactions": {"/": "QmTgzctfxxE8ZwBNGn744rL5R826EtZWzKvv2TF2dAcd9n"},
"nonce": "UJPTFZnR2CPGAzmfdYPghgrFtYFB6pf1BqMvqfiPDam8"
}
Bitcoin Transaction 比特币交易 以 YML的格式表示.
---
inputs:
- input: {/: Qmes5e1x9YEku2Y4kDgT6pjf91TPGsE2nJAaAKgwnUqR82}
amount: 100
outputs:
- output: {/: Qmes5e1x9YEku2Y4kDgT6pjf91TPGsE2nJAaAKgwnUqR82}
amount: 50
- output: {/: QmbcfRVZqMNVRcarRN3JjEJCHhQBcUeqzZfa3zoWMaSrTW}
amount: 30
- output: {/: QmV9PkR2gXcmUgNH7s7zMg9dsk7Hy7bLS18S9SHK96m7zV}
amount: 15
- output: {/: QmP8r8fLUnEywGnRRUrHB28nnBKwmshMLiYeg8udzYg7TK}
amount: 5
script: OP_VERIFY