IPFS身份管理和初始化本地仓库

IPFS身份管理和初始化本地仓库

由于IPFS网络是没有中心服务器的,各个节点之间的数据传输是需要识别各个节点的,并且要求各个节点的ID是唯一的,如果没有一定的生成规则,就带来了挑战。在IPFS中,IPFS节点ID是这样规定的。

1。节点要自己生成一个基于PKI(https://en.wikipedia.org/wiki/Public_key_infrastructure)的秘钥对。

2.对密钥对中的公钥做hash也就是HASH(节点公钥),就得到了节点的ID

默认生成的节点秘钥配置放在文件夹:~/.ipfs/config ,如果你没有自定义IPFS_PATH的话。

例如我本机的

"Identity":{

    **"PeerID"**:**"QmQeJWckGKS9C56NtyvqA3APsq4gbtS8YwPnLTb9ZT3dd4"**,

    **"PrivKey"**:**"privateKey"**

},

说明:~/.ipfs/config内容狠多,只是抽取identity

疑问:

这里如果节点作恶了,我从新生成一对密钥对就OK拉 !!!怎么办?

节点ID的使用,当两个节点需要通信的时候

1.交换两个节点的公钥

2.检测HASH(节点公钥)是否等于节点ID

3.如果检测不相等,就退出。

IPFS command 结构

IPFS每一个命令的结构大致如下

[图片上传失败...(image-f0edd7-1532334776759)]

IPFS 初始化流程

初始化命令

ipfs init

命令代码分析,主要入口文件:/Users/zhang/go/src/github.com/ipfs/go-ipfs/cmd/ipfs/init.go

init命令运行的时候

1.在postRun中检测是否配置文件所在的repo在是否存在repo.lock文件,有就代表ipfs的deamon进程存在,就退出(代码init.go 61行)

[图片上传失败...(image-7a1152-1532334776759)]

2.根据输入的options参数(可选参数中值得注意的是--bits,指定生成的秘钥的长度,默认2048 ,profile,指定生成的配置文件名称),执行doInit方法.

A。 在doInit先检测IPFS所在文件系统的读写权限。

B。 检测fsrepo是否存在了节点config文件

C。如果没有存在config,执行初始化流程如下:

细节:加密秘钥长度必须最少是2048,如果太小报错

a。调用libp2p-crypto库的GenerateKeyPair生成密钥对,加密方法RSA。其中私钥使用base64.StdEncoding.EncodeToString方法转换为字符串。公钥调用go-libp2p-peer的IDFromPublicKey方法得到字符串x,最终字符串x调用libp2p的IDB58Encode方法编码为字符串hash,这个hash就是节点ID

b。读取启动节点,也就是bootstrap peer,这些节点决定了本地节点启动的时候链接谁的问题。默认系统默认硬编码了如下节点。这些节点由IPFS官方来维护。

var DefaultBootstrapAddresses = []string{

 "/dnsaddr/bootstrap.libp2p.io/ipfs/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN",

 "/dnsaddr/bootstrap.libp2p.io/ipfs/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa",

 "/dnsaddr/bootstrap.libp2p.io/ipfs/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb",

 "/dnsaddr/bootstrap.libp2p.io/ipfs/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt",

 "/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ", // mars.i.ipfs.io

 "/ip4/104.236.179.241/tcp/4001/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM", // pluto.i.ipfs.io

 "/ip4/128.199.219.111/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu", // saturn.i.ipfs.io

 "/ip4/104.236.76.40/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64", // venus.i.ipfs.io

 "/ip4/178.62.158.247/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd", // earth.i.ipfs.io

 "/ip6/2604:a880:1:20::203:d001/tcp/4001/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM", // pluto.i.ipfs.io

 "/ip6/2400:6180:0:d0::151:6001/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu", // saturn.i.ipfs.io

 "/ip6/2604:a880:800:10::4a:5001/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64", // venus.i.ipfs.io

 "/ip6/2a03:b0c0:0:1010::23:1001/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd", // earth.i.ipfs.io

}

c。读取数据存储默认配置文件DefaultDatastoreConfig,代码: src/github.com/ipfs/go-ipfs/repo/config/init.go 25行。

数据存储

数据存储是数据存储和数据库访问的通用抽象层。它是一个简单的API,其目的是使应用程序开发以数据不可知的方式进行,允许在不改变应用程序代码的情况下无缝地交换数据存储。因此,您可以利用具有不同强度的不同数据存储,而无需将应用程序在整个生命周期内提交给一个数据存储。

代码库

https://github.com/ipfs/go-datastore

配置文件如下

func DefaultDatastoreConfig() Datastore {

 return Datastore{

 StorageMax: "10GB",

 StorageGCWatermark: 90, // 90%

 GCPeriod: "1h",

 BloomFilterSize: 0,

 Spec: map[string]interface{}{

 "type": "mount",

 "mounts": []interface{}{

 map[string]interface{}{

 "mountpoint": "/blocks",

 "type": "measure",

 "prefix": "flatfs.datastore",

 "child": map[string]interface{}{

 "type": "flatfs",

 "path": "blocks",

 "sync": true,

 "shardFunc": "/repo/flatfs/shard/v1/next-to-last/2",

 },

 },

 map[string]interface{}{

 "mountpoint": "/",

 "type": "measure",

 "prefix": "leveldb.datastore",

 "child": map[string]interface{}{

 "type": "levelds",

 "path": "datastore",

 "compression": "none",

 },

 },

 },

 },

 }

}

默认存储空间10G,每小时一次GC,挂载点2个,一个是leveldb一个是flatfs,应该也是可以配置的。

d。读取本地地址默认配置,代码位置 src/github.com/ipfs/go-ipfs/repo/config/init.go 101行。

配置如下

func addressesConfig() Addresses {

 return Addresses{

 Swarm: []string{

 "/ip4/0.0.0.0/tcp/4001",

 // "/ip4/0.0.0.0/udp/4002/utp", // disabled for now.

 "/ip6/::/tcp/4001",

 },

 Announce: []string{},

 NoAnnounce: []string{},

 API: "/ip4/127.0.0.1/tcp/5001",

 Gateway: "/ip4/127.0.0.1/tcp/8080",

 }

}

可见,本地Swarm监听4001端口,使用这个端口和其他节点通信。支持IPV4和IPV6,默认不支持UDP方式。本地Api网关,127.0.0.1:5001 ,本地资源网关127.0.0.1:8080 。

e。配置组播配置

Discovery: Discovery{

 MDNS: MDNS{

 Enabled: true,

 Interval: 10,

 },

},

使用MDNS协议来组网。在一个没有常规DNS服务器的小型网络内,可以使用mDNS来实现类似DNS的编程接口、包格式和操作语义。具体:https://www.cnblogs.com/yuweifeng/p/6409182.html

f。设置路由

Routing: Routing{

 Type: "dht",

},

g。设置挂载点

Mounts: Mounts{

 IPFS: "/ipfs",

 IPNS: "/ipns",

},

h。设置资源网管headers等信息

Gateway: Gateway{

 RootRedirect: "",

 Writable: false,

 PathPrefixes: []string{},

 HTTPHeaders: map[string][]string{

 "Access-Control-Allow-Origin": []string{"*"},

 "Access-Control-Allow-Methods": []string{"GET"},

 "Access-Control-Allow-Headers": []string{"X-Requested-With", "Range"},

 },

},

i。读取和设置swarm配置

Swarm: SwarmConfig{

 ConnMgr: ConnMgr{

 LowWater: DefaultConnMgrLowWater,

 HighWater: DefaultConnMgrHighWater,

 GracePeriod: DefaultConnMgrGracePeriod.String(),

 Type: "basic",

 },

},

D。解析配置文件

E。真正调用:fsrepo.Init(repoRoot, conf) 代码:161行。

a。写入C步骤生成的config文件到repo路径下面

b。初始化datastore空间

c。在repo下面写入版本WriteVersion

F。如果参数默认,调用addDefaultAssets写入默认readme文件到本地repo

到此为止,infs init 流程结束。

Multihash

https://github.com/multiformats/multihash

https://multiformats.io/multihash/#implementations

为何要有multihash?

本质上为了升级方便,现有的各种加密算法,不能保证以后不出问题。第三方如果依赖于使用的hash算法的名字和长度,以后升级就会带来各种各样的问题。为此,multihash就出来了,它采用TLV (type-length-value) 的方式抽象了Hash的使用~ 解决了依赖于hash 函数和 长度的问题。

在IPFS中使用multihas的地方主要是ipfs object分块和地址这里。

你可能感兴趣的:(IPFS身份管理和初始化本地仓库)