Proficient in IPFS: one of the system startups

Today, we start to look at the IPFS system from the source code. Below we use Node.JS as an example to explain the source code of IPFS. When we write the following code

const {createNode} = require('ipfs') const node = createNode() 

At the time, although there are only two simple codes, but a very large amount of code is executed internally, let us see how the system is executed and how to initialize the system.

When we execute the createNode function, the function that is actually executed is in the ipfs/core/index.js file. The code is as follows:

 module.exports.createNode = (options) => {  return new IPFS(options) } 

The IPFS object initialized above represents the IPFS system, which is in the same file and inherits from the EventEmitter object. When we initialize the IPFS object, we start executing its constructor, and then we analyze the constructor.

  1. Call the parent class constructor.
  2. Set the environment variables used by the system. First, set the system default options.
     const defaults = {  init: true,  start: true,  EXPERIMENTAL: {},  preload: {    enabled: true,    addresses: [      '/dnsaddr/node0.preload.ipfs.io/https',      '/dnsaddr/node1.preload.ipfs.io/https'    ]  } } 

    Second, verify that the option is valid.

     options = config.validate(options || {}) 

    Next, call the mergeOptions function to merge the default options with user-specified option arguments.

Finally, the init and start options of the processing options are as follows:

 if (options.init === false) {  this._options.init = false } 

If (!(options.start === false)) { this._options.start = true }

  • If a repository is specified in the option and the type is a string, or if no repository is specified, then the repository used by the setup is the default repository; otherwise, the user-specified repository is used.
     if (typeof options.repo === 'string' ||    options.repo === undefined) {  this._repo = defaultRepo(options.repo) } else {  this._repo = options.repo } 

    The default repository definition is located in the runtime/repo-nodejs.js file. The contents of this file are relatively simple, as follows:

     'use strict' 
  • Const os = require('os') const IPFSRepo = require('ipfs-repo') const path = require('path')

    Module.exports = (dir) => { const repoPath = dir || path.join(os.homedir(), '.jsipfs')

    Return new IPFSRepo(repoPath) } Because we did not specify the location of the repository, it defaults to the .jsipfs directory under the user's .jsipfs directory. Below, we look at the IPFSRepo object, which is located in the index.js file of the ipfs-repo project. Its constructor is as follows:

    Constructor (repoPath, options) { assert.strictEqual(typeof repoPath, 'string', 'missing repoPath')

     this.options = buildOptions(options) this.closed = true this.path = repoPath 

    This._locker = this._getLocker()

    This.root = backends.create('root', this.path, this.options) this.version = version(this.root) this.config = config(this.root) this.spec = spec(this.root) this.apiAddr = apiAddr(this.root) }

    In the constructor of the repository, first call the buildOptions function to set the options for the repository. This function combines the user-specified options with the warehouse default options, and handles both the storageBackends and storageBackendOptions options. Because the default repository is only specified when the repository is created, and no other options for the task are specified, the default repository uses the default options. The default options are as follows.

     {  lock: 'fs',  storageBackends: {    root: require('datastore-fs'),    blocks: require('datastore-fs'),    keys: require('datastore-fs'),    datastore: require('datastore-level')  },  storageBackendOptions: {    root: {      extension: ''    },    blocks: {      sharding: true,      extension: '.data'    },    keys: {    }  } } 

    From the default options, we found that the lock uses files, the root directory, the block directory, and the keys directory use normal file system storage, the data store uses a level data system, and the default data file suffix is .data .

    After processing the warehouse options, you can then process the warehouse. Call the function defined in the backends.js file to create the directory of the repository. Create the home directory object according to the option configuration. By default, the home directory is created in ~/.jsipfs , and then the version file, configuration file, storage rules, etc. are created in turn. .

    Note that after these actions are completed, the warehouse object is initially completed, but at this time, other directories and files are not actually created except the home directory, and their actual creation will not be performed until the initialization is started.

  • Next, generate the objects that are needed internally.
     this._peerInfoBook = new PeerBook() this._peerInfo = undefined this._bitswap = undefined 
  • this._blockService = new BlockService(this._repo) this._ipld = new Ipld(ipldOptions(this._blockService, this._options.ipld, this.log)) this._preload = preload(this)

    this._mfsPreload = mfsPreload(this) _bitswap object is actually generated in the start phase. The block service object saves the repository object and the bitswap object. The system processes the specific block by calling the put, get, and delete operations of the block service object. The specific block can be from the local repository. In the middle processing, you can also process specific blocks through the bitswap object. The bitswap object is now empty and will not be generated and set until the system startup phase.

  • Then expand the core components of the system, mainly for initialization, startup, termination, shutdown, etc. of the node.
     this.init = components.init(this) this.preStart = components.preStart(this) this.start = components.start(this) this.stop = components.stop(this) this.shutdown = this.stop this.isOnline = components.isOnline(this) 

    These commands will be explained in detail later, and will not be mentioned here.

  • Then expand some of the interaction-related components, including file-related operations.
     Object.assign(this, components.filesRegular(this)) this.version = components.version(this) this.id = components.id(this) this.repo = components.repo(this) this.bootstrap = components.bootstrap(this) this.config = components.config(this) this.block = components.block(this) this.object = components.object(this) this.dag = components.dag(this) this.files = components.filesMFS(this) this.libp2p = null // assigned on start this.swarm = components.swarm(this) this.name = components.name(this) this.bitswap = components.bitswap(this) this.pin = components.pin(this) this.ping = components.ping(this) this.pingPullStream = components.pingPullStream(this) this.pingReadableStream = components.pingReadableStream(this) this.pubsub = components.pubsub(this) this.dht = components.dht(this) this.dns = components.dns(this) this.key = components.key(this) this.stats = components.stats(this) this.resolve = components.resolve(this) 

    The above two steps can be directly called for the expansion of the system, or can be called by the program. Corresponds to the relevant commands in the command line.

  • Finally, the boot function is called to start the system.
  • At this point, the IPFS node has been started macro, and various commands can be called to play the system.

    We will continue to update Blocking; if you have any questions or suggestions, please contact us!

    Share:

    Was this article helpful?

    93 out of 132 found this helpful

    Discover more

    Opinion

    Unveiling SBF's Defense Draft of up to 250 pages I did what I believed was right.

    In the draft, SBF traced his development history, from his childhood in Palo Alto to the penthouse apartment he purch...

    Blockchain

    Exchange 5 hotspot tracking: The relationship between platform currency and IEO is like stocks and futures

    On April 26th, an online conversation on the theme of “Exchange Hotspot Tracking” was held on TokenClub...

    Market

    Solana’s Spectacular Comeback: Moons and Stumbles

    In 2023, the token has increased by over four times its starting value of $10, making it a lucrative investment for F...

    Blockchain

    After carrying a huge debt and shutting down TradeBlock, the former crypto empire DCG is now struggling for survival with one arm.

    As the liquidity crisis in encryption erupted, the market declined, and the previous blind expansion and investment h...

    Blockchain

    Lawyer's point of view | Analysis of the regulatory environment behind the investigation of the currency exchange

    Author: Hu Tao Source: The chain catcher's recent investigation of the currency exchange has triggered industry ...

    Opinion

    Former close friend to testify against SBF, list of other witnesses revealed.

    SBF's trial started on October 2nd, and his once closest friends will testify in court, becoming his biggest threat. ...