Create your own cryptocurrency using Cardano technology

Create your own cryptocurrency using Cardano technology

This is a 2 part tutorial showing how you can create your own sovereign cryptocurrency using existing Cardano software.

  • Part I (this post) explains how to set up a genesis block and get your own network of nodes to start producing blocks and bootstrap the new cryptocurrency.
  • Part II shows you how to tinker with Daedalus to customize your own wallet for the new cryptocurrency.

Part I – Node Setup

Back in the early 2010’s, creating a new cryptocurrency was a matter of forking Bitcoin Core source code, changing complex C++ source code and then firing up some PC’s, GPU’s or ASICs to mine the new crypto. Hopefully, after announcing your work on Bitcointalk, users would join in and begin to mine the coin with you, trade it and promote it on social media to bring it to life. That’s how all the early cryptos came to be.

Things have changed a lot since the days of the cryptocurrency wild west.

Third generation cryptocurrencies like Cardano allow you to easily create a new blockchain from scratch without messing with the core source code. What used to be hard-coded in binaries that you couldn’t change without a complete rebuild of the system, are now configurable options that anyone can change.

Creating a whole new cryptocurrency using Cardano is really simple. All you have to do is change the initial blockchain parameters, configure the initial nodes correctly and run the Cardano software on each node. Then comes the hard part: building a community around it! Though we can’t help you with the latter, we’ll do our best to give you all the steps to develop your own cryptocurrency using Cardano’s full node written in the Haskell language.

Note that we’re not creating a token on top of a host blockchain, like Ethereum ERC-20 tokens. This is a tutorial on how to create your very own sovereign cryptocurrency, with its own genesis block and complete blockchain.

First we’ll start with the basic building block: we need a blockchain. After we build our own blockchain using cardano-node, we’ll get a few nodes running to simulate a real network. Lastly, I’ll trick the Daedalus wallet into using our full node instead of IOHK’s official ones, so we see how our new crypto would look inside a real wallet.

If you’re successful implementing all the steps here, you’ll end up with a complete implementation of a cryptocurrency. If you want to give your new crypto a custom look, changing the logo, application name, Electron stylesheets and other Daedalus parameters should be piece of cake! (This is what 99.9% of ICO’s did back in 2017, except they didn’t implement their own blockchain.)

So let’s jump right into it!

Getting Started

I used Linux for this experiment. If you’re really into cryptocurrencies, I highly recommend you either run a Linux box or launch a Linux-based virtual machine. Cloud providers like AWS and Digital Ocean offer extremely cheap instances that you can have up and running in minutes.

Of course, Windows and Mac are fine too, but you’ll have to adapt these instructions to those OSs. Thankfully, running Linux inside Windows is now easier than ever thanks to WSL.

Build cardano-node

After you have a running Linux box, we’ll need to fetch and build cardano-node.

I’ve recently written about the adventure of trying to get the Haskell cardano-node up and running. Just follow the instructions at the end of the article and you should be good to go.

Make sure you practice the build process. Until the first stable mainnet release, the code base will change a lot and will require you to rebuild it several times a week in order to keep up with the latest developments.

After a successful build, copy cardano-node and cardano-cli to a directory in your PATH, then make sure you can call these commands from any directory:

$ which cardano-cli
/home/cryptobi/.local/bin/cardano-cli

$ cardano-cli version
cardano-cli 1.11.0 - linux-x86_64 - ghc-8.6
git rev 37cb578e5292a41c6567487fc63031191af28066

$ cardano-node version
cardano-cli 1.11.0 - linux-x86_64 - ghc-8.6
git rev 37cb578e5292a41c6567487fc63031191af28066

Funny how both cardano-cli and cardano-node return the same version string. I wonder if that’s on purpose.

So, now that we’ve got our tools in place, let’s take the first step to create our own cryptocurrency: create a genesis block!

Creating a Genesis Block

Create a directory where you’ll place all your new cryptocurrency’s files in it. I named mine my-TN for “my Test Network”, but this can be anything.

Then change into the new directory:

$ cd my-TN

Now let’s create the genesis block:

$ cardano-cli shelley genesis create --genesis-dir genesis/

This will create the genesis/ directory. Let’s see what’s inside:

$ ls genesis/
delegate-keys  genesis.json  genesis-keys  genesis.spec.json  utxo-keys

So far so good.

According to IOHK’s documentation, you can now just edit genesis.spec.json and re-run the cardano-cli command to recreate the genesis block according to your new template. This should obviously only be done during development! Once your crypto gets released, the genesis block will become immutable forever. If you decide to change your genesis block after users have already adopted your new cryptocurency, you’ll void every existing coin!

Now we must create 2 sets of genesis keys. The shelley genesis create command already created a directory for this: genesis/genesis-keys/ – so we’ll go ahead and place our keys there.

$ cardano-cli shelley genesis key-gen-genesis --verification-key-file genesis/genesis-keys/genesis1.vkey --signing-key-file genesis/genesis-keys/genesis1.skey

$ cardano-cli shelley genesis key-gen-genesis --verification-key-file genesis/genesis-keys/genesis2.vkey --signing-key-file genesis/genesis-keys/genesis2.skey

Note that these commands were copied almost verbatim (different directory name) from the IOHK genesis tutorial.

Note: If you decide to inspect the data contained in the secret files using online tools, then you should not use those same keys in production. Submitting keys anywhere, even if the recipient site has no idea what the binary data may be, compromises their security permanently. You should assume the key has been intercepted.

Our First Delegates

Since, at this point, our network is empty (we haven’t even launched it yet), we need to create a couple of original delegators to bootstrap the network:

$ cardano-cli shelley genesis key-gen-delegate \
--verification-key-file genesis/delegate-keys/delegate1.vkey \
--signing-key-file genesis/delegate-keys/delegate1.skey \
--operational-certificate-issue-counter genesis/delegate-keys/delegate-opcert1.counter

$ cardano-cli shelley genesis key-gen-delegate \
--verification-key-file genesis/delegate-keys/delegate2.vkey \
--signing-key-file genesis/delegate-keys/delegate2.skey \
--operational-certificate-issue-counter genesis/delegate-keys/delegate-opcert2.counter

(Again, the two above commands were extracted almost verbatim from IOHK documentation.)

This is what our genesis/ directory looks like now:

my-TN$ find genesis/
genesis/
genesis/genesis-keys
genesis/genesis-keys/genesis1.vkey
genesis/genesis-keys/genesis1.skey
genesis/genesis-keys/genesis2.vkey
genesis/genesis-keys/genesis2.skey
genesis/delegate-keys
genesis/delegate-keys/delegate1.vkey
genesis/delegate-keys/delegate1.skey
genesis/delegate-keys/delegate-opcert1.counter
genesis/delegate-keys/delegate2.vkey
genesis/delegate-keys/delegate2.skey
genesis/delegate-keys/delegate-opcert2.counter
genesis/utxo-keys
genesis/genesis.spec.json
genesis/genesis.json

Printing Money

Now comes the fun part: we’ll print some of our new cryptocurrency!

$ cardano-cli shelley genesis key-gen-utxo \
--verification-key-file genesis/utxo-keys/utxo1.vkey \
--signing-key-file genesis/utxo-keys/utxo1.skey

# Regen the genesis file:

$ cardano-cli shelley genesis create --genesis-dir genesis/

Now let’s take a look at our genesis/genesis.json file:

"genDelegs": {
        "70a31077572d43fac4c6348edd663b6f69d41bc11ff019a0698ba846ff78fbda": "a84143c8b8e86454c0fad0be73524ae76865b7453cb9889e7f2d9222f6171dfa",
        "cbfcf7ea48183a1a87bf49d7a8c0b53544413672484f0fd7b23281b246ec8260": "3d489081c39f76c309df743251162c4a95030c5256bbf28e636aa1ba9d1bd16e"
    },

[ ... elsewhere ... ]

"initialFunds": {
        "82065820257f27bf2d953ae27436cbe88bfc5dba8512c56c57e374c7b6c8fc23397c8bfa": 21000000000000
    },

There’s now a section containing genesis block delegations (genDelegs) and another section with initialFunds. Good.

I’ve manually set the initial funds to 21 million x million corns. 21 million coins, as a tribute to Bitcoin. I’ve also decided to call the smallest unit of our new coin a corn. (Cardano calls them Lovelaces. Every ADA holds 1 million lovelaces.)

Keys to the City

Now it’s time to generate some [more] necessary keys. The Cardano protocol, Ouroboros, requires several keys to function. I’ll explain what each of these keys are in a separate article. For now, just follow along to create your VRF and KES keys. Each node you run *must* have a set of keys. As you can tell by now, managing all the keys required to run a Cardano-based blockchain is a demanding task. At least 90% of our work so far has been creating keys!

# First create directory for the node keys
$ mkdir genesis/node-1

# Create KES and VRF keys
# Do the same for any number of node-N
$ cardano-cli shelley node key-gen-KES \
    --verification-key-file genesis/node-1/kes.vkey \
    --signing-key-file genesis/node-1/kes.skey

$ cardano-cli shelley node key-gen-VRF \
    --verification-key-file genesis/node-1/vrf.vkey \
    --signing-key-file genesis/node-1/vrf.skey

Now we need to tell everyone that these keys are valid or as the Cardano system calls them: operational. This is done by using the node’s master secret key to sign a certificate that’s basically a kind of letter of attorney which tells everyone that these keys do legitimately represent the node owner.

It’s a complex command, which I also extracted verbatim from IOHK documentation:

$ cardano-cli shelley node issue-op-cert \
--hot-kes-verification-key-file genesis/node-1/kes.vkey \
--cold-signing-key-file genesis/delegate-keys/delegate1.skey \
--operational-certificate-issue-counter genesis/delegate-keys/delegate-opcert1.counter \
--kes-period 0 \
--out-file genesis/node-1/cert

Repeat the above command for nodes 1 to N, by changing node-1 parameter for as many block producing nodes as you wish to launch initially.

Liftoff

We’re almost ready to launch our brand new blockchain! Now we need to configure cardano-node software to launch our own network. As suggested by the official documentation, we can just copy the mainnet’s configuration.yaml file and make changes to it.

$ cp /path-to/cardano-node/configuration/defaults/byron-mainnet/configuration.yaml .

$ vi configuration.yaml
# set protocol to TPraos:
Protocol: TPraos
# also change this directory
GenesisFile: genesis/genesis.json

I created two scripts to run the block producing nodes we configured throughougt: run-node-1.sh and run-node-2.sh

[wrek-sys:cardano.node.ForgeTime:Info:37] [2020-05-17 21:32:55.95 UTC] fromList []
[wrek-sys:cardano.node.Forge:Info:37] [2020-05-17 21:32:55.95 UTC] Forged block for slot 1463
[wrek-sys:cardano.node.ForgeTime:Info:37] [2020-05-17 21:32:55.95 UTC] fromList []
[wrek-sys:cardano.node.ForgeTime:Info:37] [2020-05-17 21:32:55.95 UTC] fromList [("kind",String "OutcomeTraceForgeEvent"),("difftime",Number 7.695e7),("slot",Number 1463.0),("mempoolbytes",Number 0.0),("mempoolnumtx",Number 0.0)]
[wrek-sys:cardano.node.ChainDB:Notice:27] [2020-05-17 21:32:56.07 UTC] Chain extended, new tip: (Point 1463, HashHeader {unHashHeader = da87ab2e147c6aabd2cc2bda9d978da282b723741996dec60e7c29062b3a249f})
[wrek-sys:cardano.node:Info:37] [2020-05-17 21:32:56.07 UTC] fromList [("time(ps)",Number 1.129827179761629e18),("kind",String "MeasureTxsTimeStop"),("slot",Number 1463.0)]
[wrek-sys:cardano.node.Forge:Info:37] [2020-05-17 21:32:56.07 UTC] Adopted forged block for slot 1463: HashHeader {unHashHeader = da87ab2e147c6aabd2cc2bda9d978da282b723741996dec60e7c29062b3a249f}; TxIds: []

Look, ma! No hands!

There it is. A network of cryptocurrency nodes all running on a single PC.

Now, how do you distribute the new cryptocurrency to end users?

You need to copy (or fork) the Daedalus wallet code, add your own logo / brands and stuff and bundle the custom genesis.yaml, configuration.yamland topology.yaml files with it. Before we customize Daedalus, let’s cardano-node to run as a full noded, not producing blocks.

First we need a topology.yaml file. I’ll merge the two block producers’ topology files into one. I’ve named it client-topology.yaml:

{
  "Producers": [
    {
      "addr": "127.0.0.1",
      "port": 3001,
      "valency": 1
    },
    {
      "addr": "127.0.0.1",
      "port": 3002,
      "valency": 1
    }
  ]
}

Finally, let’s try running a simple node using the same configuration.yaml as the producers and the topology.yaml we’ve just created :

$ cardano-node run \
--config configuration.yaml \
--topology client-topology.json \
--database-path /disk5/mytn \
--port 3005

It works!

[wrek-sys:cardano.node.ChainDB:Notice:5] [2020-05-17 23:51:55.45 UTC] Chain extended, new tip: (Point 9785, HashHeader {unHashHeader = 8c2fa2f7b3e39dee9ed1f9ee35c02e5ac931cdd4febbaf0d24fb94ef7f9c72cd})

Where’s Wallet

Our new cryptocurrency wouldn’t be complete without its own wallet! Here I’ll experiment with Daedalus + our full node.

As a first test, what if we started Daedalus, the official Cardano wallet, while feeding off the full node we just configured?

First, I’ll download the Byron reboot Daedalus and run it to see what configuration files.

Here’s the relevant output from ps ax :

17783 ?        Sl    54:40 cardano-node run \
--socket-path /home/cryptobi/.local/share/Daedalus/mainnet/cardano-node.socket \
--shutdown-ipc 3 \
--topology /nix/store/g04yc32yxqkn4f50xcb2ip33qicy2x2g-node-cfg-files/topology.yaml \
--database-path chain \
--port 41247 \
--config /home/cryptobi/.local/share/Daedalus/mainnet/config.yaml

Looks like the configuration files are located under a chroot’ed nix repository at /nix/store/g04yc32yxqkn4f50xcb2ip33qicy2x2g-node-cfg-files:

Unfortunate Hack

For a quick hack, I’ll back these files up and substitute them with my own, just to see what happens. (Don’t do this at home. It’ll void your warranty.)

Ooops. Looks like I broke Daedalus:

Logs say my genesis.json file is missing StartTime.

[wrek-sys:cardano.node:Debug:5] [2020-05-18 16:52:59.45 UTC] tracing verbosity = normal
There was an error parsing the genesis file: /nix/store/qd60rqsk0rjdrckg2js8dgl9jh21bd1j-mainnet-genesis.json Error: "Error in $: key \"StartTime\" not found"

Checking the genesis.json file I note that the new Genesis File format probably uses a lower case key name, since we do have a StartTime key in there:

"startTime": "2020-05-17T21:08:32.951008854Z",

I’ll go ahead and edit this. It’s a hack anyway.

    "startTime": "2020-05-17T21:08:32.951008854Z",
    "StartTime": "2020-05-17T21:08:32.951008854Z",

Leaving the two keys in now. Let’s try running the node again.

[wrek-sys:cardano.node:Debug:5] [2020-05-18 17:19:58.88 UTC] tracing verbosity = normal
There was an error parsing the genesis file: /nix/store/qd60rqsk0rjdrckg2js8dgl9jh21bd1j-mainnet-genesis.json Error: "Error in $: key \"NetworkMagic\" not found"

Again, different key name. I hope this isn’t going where I think it is. Will I have to capitalize every key in genesis.json to remain compatible with the latest Daedalus which already seems to be obsolete? Argh.

[wrek-sys:cardano.node:Debug:5] [2020-05-18 17:26:22.01 UTC] tracing verbosity = normal
There was an error parsing the genesis file: /nix/store/qd60rqsk0rjdrckg2js8dgl9jh21bd1j-mainnet-genesis.json Error: "Error in $: key \"ProtocolMagicId\" not found"

[ ... one run later ...]

[wrek-sys:cardano.node:Debug:5] [2020-05-18 17:27:48.93 UTC] tracing verbosity = normal
There was an error parsing the genesis file: /nix/store/qd60rqsk0rjdrckg2js8dgl9jh21bd1j-mainnet-genesis.json Error: "Error in $: key \"ActiveSlotsCoeff\" not found"

[ ... one run later ...]

[wrek-sys:cardano.node:Debug:5] [2020-05-18 17:30:28.87 UTC] tracing verbosity = normal
There was an error parsing the genesis file: /nix/store/qd60rqsk0rjdrckg2js8dgl9jh21bd1j-mainnet-genesis.json Error: "Error in $: key \"DecentralisationParam\" not found"

[ ... 1587 runs later ...]

Daedalus Build

Alright, the quick hack ended up taking longer than taking the long path. I’ll try a different approach now, trying to connect Daedalus directly to our running node.

Trying to run the installed Daedalus requires us to nix-chroot into ~/.daedalus. I want to play with Daedalus outside the chrooted environment though, so I’ll just try to build Daedalus from source.

Let’s clone the Github repo:

$ git clone https://github.com/input-output-hk/daedalus.git

# I guess I'll need the latest electron

$ npm i -D electron@latest

This time I won’t make the same mistakes I made building cardano-node. I’ll just follow the instructions verbatim!

$ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
$ echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
$ sudo apt update && sudo apt install yarn
$ curl https://nixos.org/nix/install | sh
$ nix-shell # this is a long running process the 1st time you run it

Apparently, the first time I ran nix-shell it decided to build every software package written since 1945. After 3+ hours of endless scrolling, nix gives me this:

error: build of '/nix/store/hsxrjsrb5jv3112iyl0p9k5kva2a1kia-package-nix.drv' failed

Checking the Daedalus instructions again, it seems like I was first supposed to edit /etc/nix/nix.conf. Sigh. So let’s do that now.

$ sudo mkdir -p /etc/nix
$ sudo vi /etc/nix/nix.conf

Add:

substituters = https://hydra.iohk.io https://cache.nixos.org/
trusted-substituters =
trusted-public-keys = hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
max-jobs = 2  # run at most two builds at once
cores = 0     # the builder will use all available CPU cores
extra-sandbox-paths = /System/Library/Frameworks

$ nix-shell

Running nix-shell now seems to be pulling binary packages from IOHK:

copying path '/nix/store/w0ndcxrc7l2kn0k2fwbvd1jgsajxgvd7-nix-tools-0.1.0.0-exe-stack-to-nix' from 'https://hydra.iohk.io'...
copying path '/nix/store/5psmim80f6hpgxk0zyqqa59pwg14lh8l-nix-tools-0.1.0.0-exe-truncate-index' from 'https://hydra.iohk.io'...
copying path '/nix/store/y0ifkdpjx6irqa0f8wgzgy2xxqqx9k2y-ouroboros-network-ec4f3af' from 'https://hydra.iohk.io'...
copying path '/nix/store/5idrh36wgya4cbbg9b8qy0fdghlg0brw-popt-1.16' from 'https://cache.nixos.org'...

Until this happened:

error: while setting up the build environment: getting attributes of path '/System/Library/Frameworks': No such file or directory

That looks like a Mac path to me, but I haven’t used a Mac for years. Something’s wrong. Let’s try the most primitive solution:

$ sudo mkdir -p /System/Library/Frameworks
$ sudo chown cryptobi /System # /...

BOOM. It worked.

[nix-shell:~/daedalus]$

OK, apparently now I’m supposed to run yarn.

$ yarn nix:selfnode
[nix-shell:~/daedalus]$ yarn dev

Finally. Habemus Daedalus.

This is great! We got our own Daedalus build running ona self node.

Our Custom Daedalus Build

So, our next step is to get this Daedalus instance talking to our local nodes instead of the selfnode instance launched by this build. It turns out this was a bit harder than I had estimated.

Since this post is getting a bit too long, I’ll continue with the custom Daedalus build on a separate post.

Please go here for the custom Daedalus build instructions.

What’s my new currency’s symbol?!

Unlike other cryptos, the Cardano system does not hard-code the cryptocurrency’s ticker in the code!

All amounts are stored in lovelaces, which is one millionth of one ADA. In Ethereum token terms, you’d say your new coin has 6 decimal places. So, if you set the total supply to 1 with 12-zeroes, then you’d have 6 decimal places of coin fractions and 6 decimal places of actual whole coins.

For example:

"maxLovelaceSupply": 21000000000000,

Means:

21,000,000.000000 CORNS

You can call it CORNS or whatever you want. The underlying system calls them lovelaces and they represent 1 millionth of your custom unit.

The only places that’ll require your ticker are (hopefully) exchanges and your end users.

It’s just a matter of adjusting your documentation and symbols on your wallet implementation!

Conclusion

As with everything else I’ve done using software from the Cardano project, this has been quite a fun ride.

In this post we’ve created our own blockchain without changing a single line of source code in the Cardano node implementation. In one of the first steps in this tutorial, we generated a genesis block.

If you actually peek inside this genesis block configuration file (genesis.json), you’ll find that it contains tens of parameters that you can modify at will. Things like epoch size, slot times, maximum coin supply and so on are all open to change. Note that if you do change any of these parameters, you’ll have an entirely new blockchain on hand. All the previous coins will no longer work under this new genesis block.

Although the long text may make it seem like a difficult process, it really is not. You can probably automate most steps in here into a single script and create a whole new cryptocurrency with a single command.

Since all this Cardano software is still under heavy development at the time of this writing, most the complexity here stems from the rapid changes and updates. Our biggest obstacles were finding documentation and browsing Github for changes (for instance when the config file required capital letters for YAML config keys, but the latest implementation doesn’t).

Once the mainnet is released and the system settles for the Haskell cardano-node implementation, everything will become easier. Scripts will be able to automate most this work and creating a new cryptocurrency will become a turnkey process.

References

Part II – Create Your Own Cryptocurrency using Cardano Technology – Building the Wallet without using nix.

[Fakedalus] – crypto.bi Daedalus Fork

Making a Shelley blockchain from scratch

What the Byron reboot means for Cardano

Daedalus Sources and Build Instructions

How to Get Started on Creating Your Own Cryptocurrency

Complete Guide on How to Create a New Alt Coin – This is a classic post on Bitcointalk. Tens of new cryptocurrencies were inspired by this post. It’s a historical record of how first generation cryptocurrencies were created.

Meta