精通IPFS | IPFS 启动之 start 函数

  • 调用创建方法创建 libp2p 对象。默认的创建方法执行如下:

    • 首先,设置默认选项。

      const libp2pDefaults = {
          datastore,
          peerInfo,
          peerBook,
          config: {
            peerDiscovery: {
              mdns: {
                enabled: get(options, 'config.Discovery.MDNS.Enabled',
                  get(config, 'Discovery.MDNS.Enabled', true))
              },
              webRTCStar: {
                enabled: get(options, 'config.Discovery.webRTCStar.Enabled',
                  get(config, 'Discovery.webRTCStar.Enabled', true))
              },
              bootstrap: {
                list: get(options, 'config.Bootstrap',
                  get(config, 'Bootstrap', []))
              }
            },
            relay: {
              enabled: get(options, 'relay.enabled',
                get(config, 'relay.enabled', true)),
              hop: {
                enabled: get(options, 'relay.hop.enabled',
                  get(config, 'relay.hop.enabled', false)),
                active: get(options, 'relay.hop.active',
                  get(config, 'relay.hop.active', false))
              }
            },
            dht: {
              kBucketSize: get(options, 'dht.kBucketSize', 20),
              enabled: false,
              randomWalk: {
                enabled: false // disabled waiting for https://github.com/libp2p/js-libp2p-kad-dht/issues/86
              },
              validators: {
                ipns: ipnsUtils.validator
              },
              selectors: {
                ipns: ipnsUtils.selector
              }
            },
            EXPERIMENTAL: {
              pubsub: get(options, 'EXPERIMENTAL.pubsub', false)
            }
          },
          connectionManager: get(options, 'connectionManager',
            {
              maxPeers: get(config, 'Swarm.ConnMgr.HighWater'),
              minPeers: get(config, 'Swarm.ConnMgr.LowWater')
          })
      }

      其中, datastore
      peerInfo
      peerBook
      options
      等来自于 IPFS 对象的相关私有属性, config
      来自于最终生成的仓库的配置文件和用户指定的相关配置。

    • 然后,调用 mergeOptions
      方法,合并默认选项与用户指定的选项。

      const libp2pOptions = mergeOptions(libp2pDefaults, get(options, 'libp2p', {}))
                          </li>
                          <li>
      

      最后,加载 core/runtime/libp2p-nodejs.js
      文件中定义的 Node 对象(继承于 libp2p
      库定义的对象),并调用其构造函数,生成 libp2p 对象。

      const Node = require('../runtime/libp2p-nodejs')
      return new Node(libp2pOptions)
                              <code>libp2p-nodejs.js</code>
      

      文件中主要定义了创建 libp2p 对象的默认选项,并把前面生成的选项与默认选项进行合并,然后调用父类的构造来创建 对象。具体的默认选项为:

      {
        switch: {
          blacklistTTL: 2 * 60 * 1e3, // 2 minute base
          blackListAttempts: 5, // back off 5 times
          maxParallelDials: 150,
          maxColdCalls: 50,
          dialTimeout: 10e3 // Be strict with dial time
        },
        modules: {
          transport: [
            TCP,
            WS,
            wsstar
          ],
          streamMuxer: [
            Multiplex
          ],
          connEncryption: [
            SECIO
          ],
          peerDiscovery: [
            MulticastDNS,
            Bootstrap,
            wsstar.discovery
          ],
          dht: KadDHT
        },
        config: {
          peerDiscovery: {
            autoDial: true,
            mdns: {
              enabled: true
            },
            bootstrap: {
              enabled: true
            },
            websocketStar: {
              enabled: true
            }
          },
          dht: {
            kBucketSize: 20,
            enabled: false,
            randomWalk: {
              enabled: false
            }
          },
          EXPERIMENTAL: {
            pubsub: false
          }
        }
      }
                          </li>
                      </ul>
      

      通过以上代码,我们可以发现创建 libp2p 的过程是比较复杂的,libp2p 对象的实际类型为 libp2p
      库中定义的对象。
      因为 libp2p 是一个非常非常重要的组件/库,即可以使用在 IPFS/Filecoin 中,也可以有独立使用,或者在其他项目中使用,鉴于它是如此的重要,所以我们以后会专门来讲解它,这里只是简单涉及。

      libp2p 对象继承于 EventEmitter
      类,所以可以触发事件,同时本身内部也有一个类型 fsm-event
      的状态变量,所以也可以认为是一个状态机对象。