- Fixed typo. - Moved concept document link to top of page. - Added link to this doc to README.md License: MIT Signed-off-by: Nitish Malhotra <nitish.malhotra@gmail.com>
6.4 KiB
IPFS : The Add command demystified
The goal of this document is to capture the code flow for adding a file (see the coreapi package) using the IPFS CLI, in the process exploring some datastructures and packages like ipld.Node (aka dagnode), FSNode, MFS, etc.
Concepts
Try this yourself
# Convert a file to the IPFS format. echo "Hello World" > new-file ipfs add new-file added QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u new-file 12 B / 12 B [=========================================================] 100.00% # Add a file to the MFS. NEW_FILE_HASH=$(ipfs add new-file -Q) ipfs files cp /ipfs/$NEW_FILE_HASH /new-file # Get information from the file in MFS. ipfs files stat /new-file # QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u # Size: 12 # CumulativeSize: 20 # ChildBlocks: 0 # Type: file # Retrieve the contents. ipfs files read /new-file # Hello World
Code Flow
UnixfsAPI.Add() - Entrypoint into the Unixfs package
The UnixfsAPI.Add() acts on the input data or files, to build a merkledag node (in essence it is the entire tree represented by the root node) and adds it to the blockstore.
Within the function, a new Adder is created with the configured Blockstore and DAG service`.
-
adder.AddAllAndPin(files)- Entrypoint to theAddlogic encapsulates a lot of the underlying functionality that will be investigated in the following sections.Our focus will be on the simplest case, a single file, handled by
Adder.addFile(file files.File).-
adder.addFile(file files.File)- Create the DAG and add toMFSThe
addFile(file)method takes the data and converts it into a DAG tree and adds the root of the tree into theMFS.https://github.com/ipfs/go-ipfs/blob/v0.4.18/core/coreunix/add.go#L508-L521
There are two main methods to focus on -
-
adder.add(io.Reader)- Create and return the root DAG nodeThis method converts the input data (
io.Reader) to a DAG tree, by splitting the data into chunks using theChunkerand organizing them in to a DAG (with a trickle or balanced layout. See balanced for more info).The method returns the root
ipld.Nodeof the DAG. -
adder.addNode(ipld.Node, path)- Add root DAG node to theMFSNow that we have the root node of the
DAG, this needs to be added to theMFSfile system. Fetch (or create, if doesn't already exist) theMFSroot usingmfsRoot().NOTE: The
MFSroot is an ephemeral root, created and destroyed solely for theaddfunctionality.Assuming the directory already exists in the MFS file system, (if it doesn't exist it will be created using
mfs.Mkdir()), the root DAG node is added to theMFSFile system using themfs.PutNode()function.-
[MFS]
PutNode(mfs.Root, path, ipld.Node)- Insert node at path into givenMFSThe
pathparam is used to determine theMFS Directory, which is first looked up in theMFSusinglookupDir()function. This is followed by adding the root DAG node (ipld.Node) in to thisDirectoryusingdirectory.AddChild()method. -
[MFS] Add Child To
UnixFS-
directory.AddChild(filename, ipld.Node)- Add root DAG node under this directoryWithin this method the node is added to the
Directory's DAG service using thedserv.Add()method, followed by adding the root DAG node with the given name, in thedirectory.addUnixFSChild(directory.child{name, ipld.Node})method. -
[MFS]
directory.addUnixFSChild(child)- Add child to inner UnixFS DirectoryThe node is then added as a child to the inner
UnixFSdirectory using the(BasicDirectory).AddChild()method.NOTE: This is not to be confused with the
directory.AddChild(filename, ipld.Node), as this operates on theUnixFSBasicDirectoryobject. -
[UnixFS]
(BasicDirectory).AddChild(ctx, name, ipld.Node)- Add child toBasicDirectoryIMPORTANT: It should be noted that the
BasicDirectoryobject uses theProtoNodetype object which is an implementation of theipld.Nodeinterface, seen and used throughout this document. Ideally theipld.Nodeshould always be used, unless we need access to specific functions fromProtoNode(likeCopy()) that are not available in the interface.This method first attempts to remove any old links (
ProtoNode.RemoveNodeLink(name)) to theProtoNodeprior to adding a link to the newly addedipld.Node, usingProtoNode.AddNodeLink(name, ipld.Node).-
[Merkledag]
AddNodeLink()The
AddNodeLink()method is where anipld.Linkis created with theipld.Node'sCIDand size in theipld.MakeLink(ipld.Node)method, and is then appended to theProtoNode's links in theProtoNode.AddRawLink(name)method.
-
-
-
-
-
adder.Finalize()- Fetch and return the DAG root from theMFSandUnixFSdirectoryThe
Finalizemethod returns theipld.Nodefrom theUnixFSDirectory. -
adder.PinRoot()- Pin all files under theMFSrootThe whole process ends with
PinRootrecursively pinning all the files under theMFSroot
-