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

    Policy

    Sam Bankman-Fried's Lawyers Swoop In Pitching for Energetic Jury Instruction Shake-Up!

    In a final attempt to secure a not-guilty verdict for their client, the Defense team referenced multiple similar case...

    Blockchain

    Speed ​​| Cryptographic Currency Derivatives Exchange: Clearing Mechanism; Bitcoin and "Great Wealth Transfer"

    Today's content includes: 1. Chat with Tang Wei of Parity about the impact of ETH to PoS on ETC. 2. Kyber's...

    Blockchain

    Clear out while the time is right? FTX and Alameda-related addresses recently transferred $30 million worth of assets.

    In September, FTX was approved for liquidation and has been frequently withdrawing large amounts of assets in the pas...

    Blockchain

    Hilariously Hot Crypto Drama: FTX and Genesis Global Trading Settle for a Cool $175 Million

    Bankruptcy Court Approves $175 Million Settlement between Cryptocurrency Companies FTX and Genesis in New York

    Blockchain

    When the PoS gold rush era is opened, who will become the next bit continent?

    background The first generation of cryptocurrency bitcoin, which brought the necessary changes to our world, and the ...

    Blockchain

    SBF Trial Week 3 Former FTX Head of Engineering Nishad Singh appears in court, confesses to embezzling user funds for political donations.

    With the appearance of former FTX Engineering Director Nishad Singh, the third week of SBF's trial has begun. Singh's...