Skip to content

Instantly share code, notes, and snippets.

@fsantanna
Last active December 9, 2015 02:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fsantanna/413e2f198a4057b26eb9 to your computer and use it in GitHub Desktop.
Save fsantanna/413e2f198a4057b26eb9 to your computer and use it in GitHub Desktop.

Building blockchains on top of IPFS:

Currently, we cannot directly manage blockchains on top of IPFS because there is no easy way to broadcast new hashes representing block proposals. IPFS is pull-driven and not push-driven, i.e., you cannot say to the world "hey, look at this new cat picture". As it has to be, clients need to request files explicitly.

Everything else required for blockchains is already present in IPFS:

  1. The p2p network.
  2. Transactions as files.
  3. Blocks as directory of transactions.
  4. Backpointers as immutable contents inside blocks and transactions.

IPFS provides the infrastructure to distribute these immutable and verifiable transactions and blocks. So, all we need is a way to broadcast hashes representing blocks for a specific blockchain.

I believe two new commands could make blockchain handling a piece of cake:

> ipfs pubsub publish <gen-block> <new-block>

> ipfs pubsub subscribe <gen-block>
    <new-block-1>
    ...
    <new-block-2>
    ...

As illustrated further, the pubsub system is more general than for building blockchains.

Representing a blockchain:

IPFS can easily represent blockchains which UNIX-like utilities can manipulate.

The genesis block:

> echo "This is the genesis block for my awesome blockchain." > genesis
> ipfs add genesis
    <gen-block-hash>

There are no restrictions on the format of blocks. For example, the genesis block could be the hash of the pdf describing the blockchain design.

New blocks and transactions:

We can represent a block with a directory full of transactions:

> mkdir b1/
> echo "First transaction" > b1/1
> mv genesis b1/previous
> ipfs add -r b1/
    <b1-hash>
> ipfs cat <b1-hash>/previous
    "This is the genesis block for my awesome blockchain."

This creates a new block b1 with one transaction 1. The block b1 points to the previous block, in this case, the genesis block.

Now, another block b2 linking back to b1:

> mkdir b2/
> echo "Another transaction" > b2/1
> mv b1 b2/previous
> ipfs add -r b2/
    <b2-hash>
> ipfs cat <b2-hash>/previous/previous
    "This is the genesis block for my awesome blockchain."

Peers will eventually disagree on the correct path down to the genesis block. The format for blocks and transactions, as well as path validations, depends on the blockchain specification.

As desired here, all design decisions are up to the implementation on top of IPFS: tokens, mining, longest chains, proof-of-whatever, encryption and signatures, timestamps, dealing with attacks (e.g., double spending), etc.

The command API:

The command-line API requires only two new commands:

> ipfs pubsub publish <gen-block-hash> <new-block-hash>

> ipfs pubsub subscribe <gen-block>
    <new-block-1-hash>
    ...
    <new-block-2-hash>
    ...

To publish blocks:

> ipfs pubsub publish <gen-block-hash> <new-block-hash>

This reads as

Propose to the network <new-block-hash> as the longest chain down to <gen-block-hash>.

The <gen-block-hash> has to be sent in advance to clients interested in interacting with this blockchain. This is the only hash clients have to pull manually and configure once on their servers.

The <new-block-hash> contents supposedly have a path down to the <gen-block-hash>. However, it is not the purpose of IPFS to check if block proposals make sense.

To subscribe for blocks:

> ipfs pusub subscribe <gen-block-hash>
    <new-block-1-hash>
    ...
    <new-block-2-hash>
    ...

This reads as

Someone in the network proposes <new-block-*-hash> as the longest chain down to <gen-block-hash>.

Again, IPFS has no idea if this proposal makes sense, delegating checks to applications built on top of it.

Applications:

There are two kinds of applications: protocols and clients.

Both kinds have no understanding of p2p networks, and just manipulate the file system as standard UNIX-like utilities:

> ipfs pusub subscribe <gen-block-X> | <proto-X.exe>
    <new-block-a>
    ...
    <new-block-f>
    ...

The <proto-X.exe> is an executable external to IPFS which implements a specific blockchain protocol.

The program would ipfs pin the chain it thinks is the longest and ipfs unpin old chains that it decides will never become the longest again. Pinned chains will tend to remain in the IPFS network, while unpinned chains might eventually disappear for good.

In this example, the program also outputs new blocks attached to the longest chain as they appear. Now, clients built on top of a specific protocol can rely on its outputs as valid longest chains:

ipfs pusub subscribe <gen-block-altcoin> | <altcoin.exe> | <ship-product.exe>

Bootstraping a node:

Bootstrapping requires no additional commands:

> <proto.exe> /ipfs/<new-block-z>
    # this may take long...
> ipfs pusub subscribe <gen-block> | <proto.exe> | <client.exe>
    # ok, start listening...

The <proto.exe> has to parse the whole chain backwards to check its validity, then it starts listening for new blocks and redirecting longest chains to <client.exe>.

Inter-Planetary Publish Subscribe

Although this document focuses on blockchains, it should be possible to build on top of ipfs pubsub any kind of protocol that uses the publish-subscribe pattern: blogs, social networks, games, and even old services such as e-mail.

> echo "This is a tweet!" | ipfs add -q | ipfs pubsub publish <gen-block-twitter>

> ipfs pubsub subscribe <gen-block-twitter> | ipfs cat
    "This is a tweet!"

These services usually do not require a strict timeline and can be much simpler than blockchains.

Implementation

The real work IPFS nodes would need to do behind the scenes is to continuously broadcast information in the p2p network. This new subsystem could use a different port that would remain closed in nodes not interested in participating in blockchains.

Also, the <gen-block> arguments of ipfs pubsub makes easy for nodes to ignore specific blockchains completely. Each node could manually provide a white list of chains of interest in ~/.ipfs/config.

These policies preserve the overall pull nature of IPFS, i.e., there is no way to force a node to subscribe for blockchain traffic or handle arbitrary <gen-block> hashes.

Looking at the IPFS Draft document (Section 3.4.4) seems like hacking with the want_list could provide a fast track to a working prototype. A special bit flag could fix a <gen-block> so that any traffic matching ipfs publish <gen-block> would be sent to the node. For more scalability, peers sharing common pubsub interests should connect directly to one another.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment