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.
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
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 theAdd
logic 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 toMFS
The
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 theChunker
and organizing them in to a DAG (with a trickle or balanced layout. See balanced for more info).The method returns the root
ipld.Node
of the DAG. -
adder.addNode(ipld.Node, path)
- Add root DAG node to theMFS
Now that we have the root node of the
DAG
, this needs to be added to theMFS
file system. Fetch (or create, if doesn't already exist) theMFS
root usingmfsRoot()
.NOTE: The
MFS
root is an ephemeral root, created and destroyed solely for theadd
functionality.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 theMFS
File system using themfs.PutNode()
function.-
[MFS]
PutNode(mfs.Root, path, ipld.Node)
- Insert node at path into givenMFS
The
path
param is used to determine theMFS Directory
, which is first looked up in theMFS
usinglookupDir()
function. This is followed by adding the root DAG node (ipld.Node
) in to thisDirectory
usingdirectory.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
UnixFS
directory using the(BasicDirectory).AddChild()
method.NOTE: This is not to be confused with the
directory.AddChild(filename, ipld.Node)
, as this operates on theUnixFS
BasicDirectory
object. -
[UnixFS]
(BasicDirectory).AddChild(ctx, name, ipld.Node)
- Add child toBasicDirectory
IMPORTANT: It should be noted that the
BasicDirectory
object uses theProtoNode
type object which is an implementation of theipld.Node
interface, seen and used throughout this document. Ideally theipld.Node
should 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 theProtoNode
prior to adding a link to the newly addedipld.Node
, usingProtoNode.AddNodeLink(name, ipld.Node)
.-
[Merkledag]
AddNodeLink()
The
AddNodeLink()
method is where anipld.Link
is created with theipld.Node
'sCID
and 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 theMFS
andUnixFS
directoryThe
Finalize
method returns theipld.Node
from theUnixFS
Directory
. -
adder.PinRoot()
- Pin all files under theMFS
rootThe whole process ends with
PinRoot
recursively pinning all the files under theMFS
root
-