this post is featured

IPFS comes to Java

InterPlanetary File System

The InterPlanetary File System (IPFS) has ambitious goals. It aims to decentralise the internet, make it more secure, and enable the creation of purely distributed applications. It combines some of the best features of the peer-to-peer protocol BitTorrent, the version control system Git and distributed hash tables. There is no central node, and nodes do not need to trust each other.

When you add a file to IPFS your node broadcasts to the network the hash of the file (This is the location of the file as far as the network is concerned). This enables any node in the network to ask your node for the file. When a node asks the network for a certain hash, it receives a list of nodes serving that hash and can download from any of them. The result is hashed locally to prove that you got what you asked for. No such thing as a man-in-the-middle attack!

I have recently implemented a Java API to IPFS. This enables easy, type safe access to a local IPFS node over HTTP. It is really simple to use! Just add the (40 KiB!) IPFS.jar to your classpath. We hope to use IPFS to replace the distributed hash table in Peergos, our secure, distributed file storage, sharing and social network.

Ensure that IPFS is installed and running (IPFS is written in Go):

# We will build from source, we're
# developers after all
sudo apt-gt install golang
# Git is used to download dependencies
sudo apt-get install git
# download and build IPFS
go get -u github.com/ipfs/go-ipfs/cmd/ipfs
# run the IPFS daemon
ipfs daemon                                  

You can then create an accessor in Java with:

IPFS ipfs = new IPFS(new MultiAddress("/ip4/127.0.0.1/tcp/5001"));

To add a file to IPFS simply,

NamedStreamable file = new NamedStreamable.FileWrapper(new File("hello.txt"));
MerkleNode addResult = ipfs.add(file);
Multihash pointer = addResult.hash;

or if you prefer to work with raw byte arrays:

byte[] contents = "G'day world! IPFS rocks!".getBytes();
String name = "hello.txt";
NamedStreamable raw = new NamedStreamable.ByteArrayWrapper(name, contents);
MerkleNode addResult = ipfs.add(raw);
Multihash pointer = addResult.hash;

To get the contents of your file back,

Multihash filePointer = Multihash.fromBase58("QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB");
byte[] contents = ipfs.cat(filePointer);

If you want to keep a copy of something someone else has added, you can “pin” it. This means that you will keep a local copy of the file, and also act as a server for it. (Files you add are automatically pinned)

Multihash file = Multihash.fromBase58("QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB");
List<Multihash> pinned = ipfs.pin.add(file, true);

Any files you retrieve are temporarily cached, and served. Periodically, the local files that aren’t pinned are garbage collected. You can force this clean up with,

ipfs.repo.gc();

If you want to explicitly remove a file from the local cache, use:

Multihash file = Multihash.fromBase58("QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB");
List<Multihash> removed = ipfs.pin.rm(file);

Unleash the power of IPFS on your JVM!