Proficient in IPFS | IPFS startup start function
preStart
function, and the other is the start
function I studied today. This function is located in the core / components / start.js file, its main role is to actually start the system, its main body is a series, the old rules we directly analyze several of its functions.
- Execute the first function, check if the repository is closed, and if so open the repository, otherwise, call the next function. The specific code is as follows:
(cb) => { self._repo.closed ? self._repo.open(cb) : cb() }
- Execute the second function, generate a libp2p object based on the repository's configuration file, and call its startup method, and then set the IPFS object's
libp2p
to the generated libp2p object. The specific code is as follows:(cb) => { self._repo.config.get((err, config) => { if (err) return cb(err)
const libp2p = createLibp2pBundle(self, config)
Libp2p.start(err => {
If (err) return cb(err)
Self.libp2p = libp2p
Cb()
})
})
}
createLibp2pBundle
function is located in the libp2p.js
file in the current directory. The execution flow of this function is as follows:
- Generate configuration objects and option objects, the former is passed in by parameters, and the latter is obtained through IPFS objects.
const options = self._options || {} config = config || {}
- Determine how to create a libp2p object. If the creation method is specified in the options object, the specified creation method is used, otherwise the default creation method is used. By default, the user does not specify a creation method, so the default creation method is used here.
const createBundle = typeof options.libp2p === 'function' ? options.libp2p : defaultBundle
- Get the information needed to create a libp2p object from an IPFS object.
const { datastore } = self._repo const peerInfo = self._peerInfo const peerBook = self._peerInfoBook
- Call the create method to create a libp2p object. The default creation method is as follows:
- First, set the default options.
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') }) }
Among them,
datastore
,peerInfo
,peerBook
,options
and other related private attributes from IPFS objects,config
comes from the configuration file of the final generated warehouse and the user-specified configuration. - Then, call the
mergeOptions
method to merge the default options with the user-specified options.const libp2pOptions = mergeOptions(libp2pDefaults, get(options, 'libp2p', {}))
- Finally, load the Node object defined in the
core/runtime/libp2p-nodejs.js
file (inherited from the object defined by thelibp2p
library) and call its constructor to generate the libp2p object.const Node = require('../runtime/libp2p-nodejs') return new Node(libp2pOptions)
libp2p-nodejs.js
file mainly defines the default options for creating libp2p objects, and merges the previously generated options with the default options, and then calls the constructor of the parent class to create the object. The specific default options are:- Where is the blockchain enterprise settled? 7 urban blockchain special support measures competition
- Why is it true that Facebook currency is really important?
- Ethereum Essence: Complex Consensus Agreement Operation
{ 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 } } }
From the above code, we can find that the process of creating libp2p is more complicated. The actual type of
libp2p
object is the object defined in thelibp2p
library. - First, set the default options.
Because libp2p is a very, very important component/library that can be used in IPFS/Filecoin, it can be used independently, or in other projects. Since it is so important, we will specifically explain it in the future. This is just a simple matter.
The libp2p object inherits from the EventEmitter
class, so it can trigger an event, and it also has a state variable of type fsm-event
internally, so it can also be considered a state machine object.
start
method of the libp2p object to start the libp2p object. When the libp2p object starts successfully, save it in the same name property of the IPFS object. The specific code is as follows:
libp2p.start(err => { if (err) return cb(err) self.libp2p = libp2p cb() }
The start
method of the libp2p object sets the internal state to start
, which causes libp2p to call its _onStarting
method and start the startup process. The specific processing is as follows:
- Check if there is a specific transmission method configured, such as TCP. If no transfer method is specified, an exception is thrown. By default, three transmission methods such as TCP, WS, and wsstar are configured.
- Check all multiaddr addresses of the node. If no node ID is specified, the address is appended with /p2p/node ID. The peerInfo of the libp2p object is derived from the
peerInfo
of the IPFS object, which is generated and initialized in thepreStart
function. The includedmultiaddr
is from theAddresses.Swarm
array of the configuration file,/p2p-websocket-star
generated bylibp2p-nodejs.js
, The/p2p-circuit/ipfs/节点ID
generated by the previous constructor. The last address is only when themodules.streamMuxer
andrelay.enabled
are configured, that is, when stream multiplexing and circuit relay are enabled, when the circuit relay object is generated when theenableCircuitRelay
method of theswitch.connection
object is called in the constructor. Will be generated and added to the address of the node information object. After this step, themultiaddrs
final node information object becomes"/ip4/0.0.0.0/tcp/4002/ipfs/节点ID
,/ip4/127.0.0.1/tcp/4003/ws/ipfs/节点ID
,/p2p-websocket-star/ipfs/节点ID
,/p2p-circuit/ipfs/节点ID
form. - Traverse all the transport methods specified by the peer node. If a transport method can process the address specified by the node, it is saved to the
switch.transport
object (of type TransportManager). The purpose of this step is to filter the transmission method with the address of the node. Only the transmission method that can handle an address is saved to theswitch.transport
object. However, each transfer method is saved to the_transport
array of the libp2p object itself. - Start all services serially. For example: switch service, DHT service, node discovery service, etc., if these services are configured. The switch object manages all network communication related services. It is also a state machine. It usually changes the state to execute different methods. When it starts its service, it will finally execute the
_onStarting
method. This method will make all available (ie, there is an address. The transport object of the listener starts to listen, for example, the TCP transport method listens on port 4002. After the node discovery service finds the node, it will trigger the eventpeer:discovery
, and will save the discovered node to thepeerBook
. If the current number of connections is less than the specified number, the connection will be made. - After all services are started, it traverses all the addresses saved in the
peerBook
, triggers the eventpeer:discovery
, and connects if the current number of connections is less than the specified number.
- First, generate an IPNS object and set the
_ipns
of the IPFS object to generate an IPNS object.const ipnsRouting = routingConfig(self) self._ipns = new IPNS(ipnsRouting, self._repo.datastore, self._peerInfo, self._keychain, self._options)
- Then, generate a Bitswap object and set the
_bitswap
of the IPFS object to the generated Bitswap object, and call the latter's startup method;self._bitswap = new Bitswap( self.libp2p, self._repo.blocks, { statsEnabled: true } ) self._bitswap.start()
The Bitswap object is another very object in the IPFS/libp2p architecture. It determines whether to load a block from a local repository or request a block from another node in the network. It also determines whether another node requests a block request. Its
start
method in turn starts theWantManager
object (an object that periodically sends request messages to other nodes),Network
object (how a specified libp2p/switch object handles the bitswap protocol, and listens for libp2p object node connection/disconnection events) Object),DecisionEngine
object (an object that determines whether to respond to requests from other nodes). - Next, call the
setExchange
method of the blockService object to set the object of the former swap block to the newly generated Bitswap object.self._blockService.setExchange(self._bitswap)
Before the method is executed, when the block service object request block is called, the block is loaded from the local warehouse; when the method is executed, the block service object needs to determine the block through the bitswap object when requesting the block. Where did you get it?
- Next, call the
start
method of several objects to start.self._preload.start() self._ipns.republisher.start() self._mfsPreload.start(cb)
The
start
method of the preloaded object simply sets the internal variablestart
to false; the IPNS starts, and the analysis of the IPNS will be analyzed later, skipped here. The startup method of_mfsPreload
is also relatively simple, just call thestat
method of thefiles
object of the IPFS object and load the root directory. The root directory object is initialized during the initialization function, savinginit-files/init-docs/
.
When several functions of the series
method are executed, the system basically starts up. The last action to be executed is to call the done
function defined in the start
function and set the state to running.
When the done
function is completed, the IPFS system is started.
We will continue to update Blocking; if you have any questions or suggestions, please contact us!
Was this article helpful?
93 out of 132 found this helpful
Related articles
- DApp's "AARRR" User Operation Strategy (on) | PANews Report Interpretation
- Market Analysis: BTC slowly climbed the resistance level, and it was a long and short matchup.
- Google zooms in and builds a hybrid cloud blockchain application using ChainLink Oracle
- DeFi Lending Overview | May 2019 News
- She Knows | Kill Wall Street? This is not what DeFi has to do!
- finally come! The Bitcoin futures contract of the Bakkt exchange of the parent company of the NYSE will open the test on July 22.
- Academic orientation makes Bitcoin more secure, how does the Erlay protocol save 84% of the bandwidth of the node?