Building dapps on Ethereum – part 5: Ethereum Name Service and Swarm

A common usability problem with cryptographic systems like blockchains is that accounts, smart contracts and content on the blockchain are addressed with hashes like 0x7eF963588706a8d39D481634eB46f5c54A04c584. These addresses are easy for machines to securely verify but hard for humans to type and remember. And anything that’s difficult for humans creates vulnerability vectors, like phishing attacks by using an address that looks similar but is owned by a malicious person.

Before we begin

If you haven’t already, I would recommend you to read the previous posts in this series:

What is the Ethereum Name Service?

The Ethereum Name Service (ENS) attempts to reduce these usability and security problems by allowing one to use an address like dickolsson.eth instead of 0x7eF963588706a8d39D481634eB46f5c54A04c584. It’s very similar to the Domain Name Service (DNS) that let you use dickolsson.com instead of 46.232.178.79.

In this blog post we’ll learn how to deploy ENS locally and use ENS names to address content on Swarm which I covered in part 4 of this series. Note, we will not use ENS to address wallet accounts or smart contracts (at least not right now). Throughout this blog post series we will use sample code from the Iron Doers project which is a quite simple concept briefly described in a practical example of using blockchains and the project’s whitepaper.

How does Ethereum Name Service work?

ENS is beautifully simple. There are three main concepts that all are represented as smart contracts on the blockchain. They are (1) the ENS root (2) many registrars (3) many resolvers.

It should be mentioned that ENS is still in its infancy (as with most blockchain things). There’s gaps to fill and improvements to be made, but the system is already peer-reviewed by the Ethereum community and in use on its public network.

1. The ENS root

The ENS root is a very simple smart contract that mainly keep track of two things (1) registrars responsible for specific top-level domains (TLD) and (2) what resolver to use for a particular domain.

The ENS root is currently maintained as democratic autonomous organisation (DAO) where at least 4 of the 7 trustees need to agree on changes to the ENS root (such as adding additional registrars). Read more about the ENS’ plans to further democratise and decentralise the decision making on their website.

2. Registrars

ENS registrars are very similar to DNS registrars, i.e. they are the entity (a smart contract for Ethereum) responsible for managing specific top-level domains (TLD), like the .eth TLD on the public Ethereum network.

3. Resolvers

ENS resolvers are smart contracts responsible for the actual translation of hashes to human-readable names.

One ENS name can resolve to a few different things at once. The two most important things for dapps are (1) addresses for wallets or smart contracts (2) content hashes on the Swarm platform. The latter is what we’ll focus on in this blog post.

Installing ENS locally

In order to properly test and develop a dapp using ENS names you have to deploy all required ENS contracts locally and configure things like Swarm and your Ethereum browser to use the ENS root for your local blockchain. The ENS system was defined in the Ethereum Improvement Proposal #137 and we will use existing implementations of this standard to help with our deployment.

The Ethereum Foundation is hosting a Github repository with the ENS reference implementations that we’ll use:

  1. ENS root abstract interface
  2. ENS root contract
  3. First-in-first-served (FIFS) registrar contract
  4. Public resolver contract

The ENS root and resolver contracts above are very similar to the implementation that’s deployed on the public Ethereum network (i.e. the .LLL contracts). The registrar contract for .eth on the public network is implemented like a “Vickrey auction”, as opposed to FIFS (which’d be a bit chaotic on the public net). But for local development FIFS is good.

Start by copying all four .sol contracts that was linked above into your contracts/ directory. Next, we need a deployment script that will (1) deploy the ENS root contract (2) deploy the FIFS registry contract for the .test TLD (3) deploy the public resolver contract (4) register the irondoers.test domain (5) tell the ENS root to use the public resolver for the irondoers.test domain.

Next steps are to start your local blockchain, set up accounts, start mining, compiling and migrating all contracts to the blockchain. For more detailed instructions and commands for doing these steps see see part 4 of this series.

After migrating your contracts you essentially have a full ENS system running locally, nice! Take note of the various contract addresses because you’ll need them to interact with ENS later on!

$ truffle migrate --reset

Using network 'development'.
Running migration: 1_initial_migration.js
  Replacing Migrations...
  Migrations: 0x80a6e733991d7068e9683106f6a2c935d51462f5
Saving successful migration to network...
Running migration: 2_deploy_contracts.js
  Replacing IronDoers...
  IronDoers: 0x4e87c83e70ad3917d1e3b7b39915e90e837f9aa4
Saving successful migration to network...
Running migration: 3_local_ens.js
  Replacing ENS...
  ENS: 0x3b5cc4bb784f805d1e7670695231f25f941f129a
  Replacing FIFSRegistrar...
  FIFSRegistrar: 0x5e6edd79c7917fc38fcd5b89ee15a5fdb5e93ef8
  Replacing PublicResolver...
  PublicResolver: 0xe9a51737bbef33f5e14e26ff433860267b225de4
Saving successful migration to network...

Using ENS with Swarm

With ENS deployed on our local blockchain it’s time to start addressing some Swarm content! But first we need some content on Swarm. The only thing we need to add is a pointer to our ENS address. Replace with your own addresses accordingly and don’t forget to start your local geth node and mining before starting Swarm!

$ swarm --bzzaccount MAINACCOUNT \
  --ens-addr 0x3b5cc4bb784f805d1e7670695231f25f941f129a \
  --datadir ./chain/ \
  --ens-api ./chain/geth.ipc \
  --verbosity 4 \
  --maxpeers 0

Then upload some content to Swarm and take note of the content hash of the upload:

$ swarm --recursive --defaultpath=www/index.html up www/
c777819a8eaa98d61615d94be49cd3bfaa95a2ccbe0225a3c3cf354777f33c0f

Addressing content

In order to address content we need to interact with the ENS contracts. At the moment there are little-to-none convenient tooling for doing this, so we will interact with our contracts directly from the geth console! Start by attaching to the console in a new terminal tab.

$ geth attach ipc:./chain/geth.ipc

Next, we will use a utility script that you can find in the example repository. Put this script in your repository’s scripts/ directory as well. This utility script defines the Application Binary Interface (ABI) for each contract along with the namehash function that we need to translate human-readable names into the format that ENS understands.

In the console we’ll first define some handy variables, namely our main account and an instance of the PublicResolver contract. Replace with your own addresses accordingly.

> loadScript('./scripts/ensutils.js');
> var accounts = personal.listAccounts;
> var resolver = PublicResolver.at('0xe9a51737bbef33f5e14e26ff433860267b225de4');

Once we have these handy variables defined we can start interacting with ENS! Let’s start by setting the Swarm content hash for the irondoers.test domain which we registered in our deployment script earlier. Important — note the 0x prefix on the Swarm hash that we got from the upload output earlier.

> resolver.setContent(namehash('irondoers.test'), '0xc777819a8eaa98d61615d94be49cd3bfaa95a2ccbe0225a3c3cf354777f33c0f', {from: accounts[0]});

Now you just need to wait for this Ethereum transaction to be mined (which can take a few minutes) and then you should be able to access your Swarm content with the domain name instead of a hash!

When accessing our dapp through the HTTP gateway, this is what it looked like before we had a ENS name registered:

This is what it looks like with the HTTP gateway, but after setting up our ENS name:

This is what it’ll look like when browsers understand the Swarm protocol directly without needing a HTTP gateway: