62

IPFS初窥3

 5 years ago
source link: http://www.hi-roy.com/2018/10/10/IPFS初窥3/?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

在上一篇文章中记录到了IPFS的 BitSwap 协议,今天接着往下看关于 Object 的部分。

Merkle DAG

Merkle DAG是IPFS核心概念之一,在Git的数据结构上进行了改造。理解Merkle DAG之前先来了解下 Merkle Tree

简单说,Merkle Tree是一种特殊的树结构,其叶子节点的值为包含记录的哈希值,而非叶子节点的值为子节点哈希值合并后的哈希结果,一图胜千言:

3UniqiU.png!web

Merkle Tree最常见的一个应用就是数据验证领域了,这种数据结构可以大量减少验证所需传输的数据量,在 Top Hash 已知的情况下想验证L3中的数据是否被篡改过,只需要向一个可信任的中心请求获取 Hash0Hash1-1 即可。

正由于比特币中将Merkle Tree的根哈希值包含在了区块头中,所以各种轻钱包(SPV)才得以出现。

ENZVj2v.png!web

而Merkle DAG则是一种 有向无环图 结构,而且和Merkle Tree有个很重要的区别就是Merkle DAG中准许非叶节点存储数据。IPFS中数据结构定义如下:

type IPFSLink struct {
  Name string
  Hash Multihash
  Size int
}

type IPFSObject struct{
  links []IPFSLink
  data []byte
}

首先我们有这样一个目录结构:

ipfs
├── imgs
│   └── 1.jpg
├── test.txt
└── video
    └── paxos和分布式系统.mp4

然后执行 add 命令添加:

ipfs add -r ipfs
added QmTBGNDfodpscKje46wyTmzsPsJ6REWebionWK9dVc2Cms ipfs/imgs/1.jpg
added QmRmfJ8RYrULTZkjt9H11kkPBswrzVQXf36QAF3XoBG6XZ ipfs/test.txt
added Qme5oV4uKLA2BDVjFtqiCfFqv74LZXTqG1oiuu5gshqvk7 ipfs/video/paxos和分布式系统.mp4
added QmQEwN1jbjPPAnfjnbXjCi92yKu7gZbZnmK2niotz4d8oK ipfs/imgs
added QmVYaDuyoS4otNXnQ7WRbBP4ZZuLi7PLhyz2LV9vLWVwWb ipfs/video
added QmPkbxXPM2hY97NR8Tf25KZxysWn4FZrsuPwD8ztYM32j4 ipfs
 53.15 MiB / 53.16 MiB [=============================================================================================================================================================]  99.98%

这里插一句,在浏览器中访问

http://localhost:8080/ipfs/QmTBGNDfodpscKje46wyTmzsPsJ6REWebionWK9dVc2Cms

http://localhost:8080/ipfs/QmQEwN1jbjPPAnfjnbXjCi92yKu7gZbZnmK2niotz4d8oK/1.jpg

http://localhost:8080/ipfs/QmPkbxXPM2hY97NR8Tf25KZxysWn4FZrsuPwD8ztYM32j4/imgs/1.jpg

这3种访问路径都可以最终得到 1.jpg 这个图片。

可以使用 ls 命令查看文件切分情况:

ipfs ls -v Qme5oV4uKLA2BDVjFtqiCfFqv74LZXTqG1oiuu5gshqvk7
Hash                                           Size     Name
QmexC2a5eSkVuoErKhAjxpMt6DJoQeS57T3yU1cxCpb3Tu 45623854
QmR2GQi1DhvGzZ1Ra1fgpwKBTd9ubt9aPUSCvqMZPHB3cp 10103195

可以看出,mp4文件被切分成了2部分。

再使用 object get 命令查看 ipfs 这个文件夹的DAG:

ipfs object get QmPkbxXPM2hY97NR8Tf25KZxysWn4FZrsuPwD8ztYM32j4

{
  "Links": [
    {
      "Name": "imgs",
      "Hash": "QmQEwN1jbjPPAnfjnbXjCi92yKu7gZbZnmK2niotz4d8oK",
      "Size": 18418
    },
    {
      "Name": "test.txt",
      "Hash": "QmRmfJ8RYrULTZkjt9H11kkPBswrzVQXf36QAF3XoBG6XZ",
      "Size": 18
    },
    {
      "Name": "video",
      "Hash": "QmVYaDuyoS4otNXnQ7WRbBP4ZZuLi7PLhyz2LV9vLWVwWb",
      "Size": 55727234
    }
  ],
  "Data": "\u0008\u0001"
}

也和上面给的数据结构定义一致。

还有更重要的一点,IPFS准许使用者使用 block 相关命令直接操作Merkle DAG中的数据,比如:

echo "hi roy" | ipfs block put
QmUHW9uK8aKYHNSSJwS1AnnBt1dV6wbKmDWDr8tmRk9pXo

ipfs block get QmUHW9uK8aKYHNSSJwS1AnnBt1dV6wbKmDWDr8tmRk9pXo

hi roy

有这个功能可玩性就很高了,白皮书中给出了几种结构:

  • 键值对存储(key-value stores)
  • 关系型数据库(traditional relatioinal databases)
  • 三元组存储(Linked Data triple stores)
  • 文档发布系统(Linked document publishing systems)
  • 通信平台(Linked communications platforms)
  • 加密货币区块链(cryptocurrency blockchains)

再插一句,很多小伙伴不知道如何向已经存在的文件夹中添加新文件,比如想向 ipfs 目录添加文件 test2.txt :

ipfs add test2.txt
added QmUARAWmSHC3aiWhYFcGfQGEyfAKdUPWqFHxemY3iDJDRM test2.txt
 11 B / 11 B [=======================================================================================================================================================================] 100.00%

 ipfs ls -v QmPkbxXPM2hY97NR8Tf25KZxysWn4FZrsuPwD8ztYM32j4
Hash                                           Size     Name
QmQEwN1jbjPPAnfjnbXjCi92yKu7gZbZnmK2niotz4d8oK 18418    imgs/
QmRmfJ8RYrULTZkjt9H11kkPBswrzVQXf36QAF3XoBG6XZ 18       test.txt
QmVYaDuyoS4otNXnQ7WRbBP4ZZuLi7PLhyz2LV9vLWVwWb 55727234 video/

可以发现文件并没有添加进文件夹中,而仅仅是获得了一个自己的哈希值。可以使用下面的命令:

ipfs object patch add-link QmPkbxXPM2hY97NR8Tf25KZxysWn4FZrsuPwD8ztYM32j4 test21.txt QmUARAWmSHC3aiWhYFcGfQGEyfAKdUPWqFHxemY3iDJDRM

QmZzY6fgW2ndjoAXpa2gMSaJ3c8h6hzq1TFusdF33u2jvy

这里会返回一个新的哈希值,查看这个发现文件已经被添加进去了:

ipfs ls -v QmZzY6fgW2ndjoAXpa2gMSaJ3c8h6hzq1TFusdF33u2jvy
Hash                                           Size     Name
QmQEwN1jbjPPAnfjnbXjCi92yKu7gZbZnmK2niotz4d8oK 18418    imgs/
QmRmfJ8RYrULTZkjt9H11kkPBswrzVQXf36QAF3XoBG6XZ 18       test.txt
QmUARAWmSHC3aiWhYFcGfQGEyfAKdUPWqFHxemY3iDJDRM 19       test21.txt
QmVYaDuyoS4otNXnQ7WRbBP4ZZuLi7PLhyz2LV9vLWVwWb 55727234 video/

注意存储后的文件名是 ipfs object patch add-link 中指定的值,而不是原文件名。再多说一句,这个命令需要的参数仅仅是哈希值,换言之如果你知道其他人的link地址也可以加到自己的文件下。

另外,最新的文件系统已经变成IPLD了,是Merkle DAG的一个变种。

IPNS

由上面的例子也可以看出来,在IPFS中每次新增、修改某个文件都会导致哈希值的变化,这对于实际应用中是十分不便的。为了处理这个问题,IPFS中引入了一个可变命名空间的概念——IPNS(InterPlanetary Name Space),结合之前说的 路由系统 实现了”不可变的内容”和”可变的引用”的组合(可以结合编程语言中指针的概念):

routing.setValue(NodeId,<ns-object-hash>)

之前说过每个节点的NodeID来源与其公钥的哈希值,那么给每个节点分配一个可变命名空间 /ipns/<NodeID> ,用户将私钥签名过的数据发布到这个路径上,别的用户下载这个数据时可以检查签名是否和公钥、NodeID匹配来验证真实性。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK