IPNS
在ipfs中,一个文件的Hash值完全取决于其内容,修改它的内容,其相应的Hash值也会发生改变。如果我们把修改前后的文件都通过ipfs add
添加到ipfs网络中,那么我们将可以通过这两个Hash值访问到前后两个版本的内容。这种静态特性有利于提高数据的安全,比如 Alice 可以将一份自己签名(私钥加密)的文件放到ipfs中,那么即使她后来对文件进行了修改并重新签名和发布,那么之前的文件依然存在,她不能抵赖曾经发布过老版本的文件。但对于一些需要保持动态性的文件来说,比如网页,在新版本出现后,旧版本的内容将毫无意义。并且,总不能要求网页访问者每次要在浏览器中输入不同的ipfs地址来访问不同时期的网页吧。
IPNS(Inter-Planetary Naming System)提供了一种为文件增加动态性的解决方案。它允许节点的PeerID限定的命名空间提供一个指向具体ipfs文件(目录)Hash的指针,通过改变这个指针每次都指向最新的文件内容,可以使得其他人始终访问最新的内容。
例子
> echo "This is old version file" > myfile.txt
> ipfs add myfile.txt
added QmQECo2p8LdVcjtkEWDVNVM7Hrsc7arW52P5vz5BVuvEgR myfile.txt
使用ipfs publish
命令发布本节点ipns到ipfs的映射
> ipfs name publish /ipfs/QmQECo2p8LdVcjtkEWDVNVM7Hrsc7arW52P5vz5BVuvEgR
Published to QmQQ5t88W44Je5WgvmgpV1xSZTg1y5UXdYFHcQQ7EayxwR: /ipfs/QmQECo2p8LdVcjtkEWDVNVM7Hrsc7arW52P5vz5BVuvEgR
而QmQQ5t88W44Je5WgvmgpV1xSZTg1y5UXdYFHcQQ7EayxwR
正是本节点的ID,这一点可以通过ipfs id
看到
ipfs id
{
"ID": "QmQQ5t88W44Je5WgvmgpV1xSZTg1y5UXdYFHcQQ7EayxwR",
......
使用命令ipfs resolve
可以解析ipns到ipfs的映射关系
> ipfs name resolve QmQQ5t88W44Je5WgvmgpV1xSZTg1y5UXdYFHcQQ7EayxwR
/ipfs/QmQECo2p8LdVcjtkEWDVNVM7Hrsc7arW52P5vz5BVuvEgR
在本地执行该命令,很快就可以得到结果。如果在其他节点执行,会花费一些时间。
可以看出解析的结果正是myfile.txt文件的内容。
这一点也可以在浏览器中验证
在ipfs.io/ipfs/直接输入文件内容的Hash
在ipfs.io/ipns/输入节点的id
现在对文件进行修改,并添加到ipfs网络
> echo "This is new version file" > myfile.txt
> ipfs add myfile.txt
added Qmdzqe3yA4JZM5wQe2hV8pfi9CA7aWUq8vHAJd7p7USJQb myfile.txt
再修改ipns到ipfs的映射关系,使本节点的id映射到新的文件内容Hash
> ipfs name publish Qmdzqe3yA4JZM5wQe2hV8pfi9CA7aWUq8vHAJd7p7USJQb
Published to QmQQ5t88W44Je5WgvmgpV1xSZTg1y5UXdYFHcQQ7EayxwR: /ipfs/Qmdzqe3yA4JZM5wQe2hV8pfi9CA7aWUq8vHAJd7p7USJQb
验证其映射关系
> ipfs name resolve QmQQ5t88W44Je5WgvmgpV1xSZTg1y5UXdYFHcQQ7EayxwR
/ipfs/Qmdzqe3yA4JZM5wQe2hV8pfi9CA7aWUq8vHAJd7p7USJQb
在浏览器中验证:
ipfs + 新Hash显示新内容
ipns + 节点ID 显示新内容
ipfs + 旧Hash 显示旧内容
上面的例子中,我们修改ipns下的节点ID和ipfs文件内容的映射关系,使得虽然访问的是同一个地址但实际访问的文件内容却不相同,这不仅适用于单个文件,我们完全可以对一个目录作这种操作。
但是一个节点的ID只有一个,假设我需要同时保留多个这样的映射实例,该怎么办呢?
其实ipns的映射关系除了节点ID
<->文件内容
,还有一种是key
<->文件内容
通过ipfs key list
命令可以看到本节点的key
> ipfs key list -l
QmQQ5t88W44Je5WgvmgpV1xSZTg1y5UXdYFHcQQ7EayxwR self
可以看到,节点默认具有一个名为self
的key,它的值正是节点ID。
而在ipfs name publish
命令的完整形式是
ipfs name publish [--resolve=false] [--lifetime=<lifetime> | -t] [--ttl=<ttl>] [--key=<key> | -k] [--] <ipfs-path>
注意其中的key,如果不带这个参数,那么久表示使用默认的key, 也就是节点ID。
可以使用ipfs key gen
创建新的key,这里创建一个名为another
的key
> ipfs key gen --type=rsa --size=2048 another
QmYTpEqtNYvNFUwFysuRsEufNDJJBBEJfqsqrFXDT93sEE
> ipfs key list -l
QmQQ5t88W44Je5WgvmgpV1xSZTg1y5UXdYFHcQQ7EayxwR self
QmYTpEqtNYvNFUwFysuRsEufNDJJBBEJfqsqrFXDT93sEE another
尝试用新的key,映射一个ipfs文件内容
> echo "This is another file" > another.txt
> ipfs add another.txt
added QmPoyokqso3BKYCqwiU1rspLE59CPCv5csYhcPkEd6xvtm another.txt
> ipfs name publish --key=another QmPoyokqso3BKYCqwiU1rspLE59CPCv5csYhcPkEd6xvtm
Published to QmYTpEqtNYvNFUwFysuRsEufNDJJBBEJfqsqrFXDT93sEE: /ipfs/QmPoyokqso3BKYCqwiU1rspLE59CPCv5csYhcPkEd6xvtm
用ipfs resolve
解析
> ipfs resolve /ipns/QmYTpEqtNYvNFUwFysuRsEufNDJJBBEJfqsqrFXDT93sEE
/ipfs/QmPoyokqso3BKYCqwiU1rspLE59CPCv5csYhcPkEd6xvtm
总结
IPNS可以为ipfs的动态内容提供映射,用户通过publish
操作,使得其他人访问固定的IPNS地址就可以最终访问到不同的ipfs文件内容。