How to Train your Jörmungandr Manual

Table of Contents

Introduction

Welcome to the Jörmungandr User Manual.

Jörmungandr is a implementation of a distributed ledger full node, written in rust, with the initial aim to support Ouroboros type of consensus protocol.

A full node is a participant of a blockchain network, continuously making, sending, receiving and validating blocks. Each full node in the network is responsible to ensure the protocol is followed.

The Jörmungandr has been with us since the dawn of time. In Norse mythology the Jörmungandr fulfilled the responsibility of being "The Midgard Serpent". Earlier civilizations such as the Ancient Egyptians also knew of the Jörmungandr, though differently, as the serpent that eats its tail, the Ouroboros. In modern times the Jörmungandr rarely appears, if at all, but only appears during hard times when the hero within us is revealed, only to those who have the keenest sense of attention earned by hard training and only to those who wield the Fractalide sword. The Jörmungandr is one of two dragons the sword commands. If the inexperienced have yet to earn their sword, they may do so by trying to pull the below sword from their screen.

Fractalide Sword

1. Quickstart

This quickstart section will allow you to

  • connect through to the luceo blockchain

  • setup your own luceo stakepool

  • educate you on the finer details of jcli subcommands.

1.1. Installation

The software bundles 2 command line programs:

  • jormungandr, the node;

  • jcli, the Jormungandr Command Line Interface, a low level program that interact with the node.

1.1.1. Install from a release

This is the recommended method. Releases are available at the release section.

1.1.2. Install from source

Jormungandr’s source code is available at github. Follow the instructions to build the software from source.

1.2. Help and auto completion

All commands come with usage help, find out by adding --help or -h to the end of the command.

jcli has a feature which allows you to generate auto completion:

jcli auto-completion bash ${HOME}/.bash_completion.d

Supported shells are: bash, fish, zsh, powershell and elvish.

Ensure ${HOME}/.bash_completion.d directory exists on your hard disk. In order to use auto completion you still need to:

source ${HOME}/.bash_completion.d/jcli.bash

You can also put it in your ${HOME}/.bashrc so that it’s loaded whenever you enter your shell.

1.3. Passive Node

The passive Node is the most common type of node on the network, it doesn’t create blocks and is mostly used for wallets, explorers or relays.

In order to start the node, you first need to gather the blockchain information you need to connect to.

  1. the hash of the genesis block of the blockchain, this will be the source of truth of the blockchain. It is 64 hexadecimal characters.

  2. the trusted peers identifiers and access points.

The above information can be found at luceo connection information.

This information is essential for the correct starting of your node.

The genesis block is the first block of a blockchain. It contains static initialization parameters such as the initial funds. Your node will utilise the hash to retrieve the genesis block from the other peers. Once obtained the hash is used to verify the integrity of the downloaded genesis block.

Trusted peers are public nodes in the network your node will trust in order to initialise participate in the Peer To Peer network. More details to come.

1.3.1. The node configuration

Your node configuration file may look like the following:

Note

This config shouldn’t work as it is, the ip address and port for the trusted peer should be those of an already running node. Also, the public_address ('u.x.v.t') should be a valid address (you can use an internal one, eg: 127.0.0.1). Furthermore, you need to have permission to write in the path specified by the storage config.

storage: "/mnt/luceo/storage"

rest:
  listen: "127.0.0.1:8443"
  prefix: "api"

peer_2_peer:
  trusted_peers:
    - id: 1
      address: "/ip4/104.24.28.11/tcp/8299"
  public_access: "/ip4/u.v.x.y/tcp/8299"
  topics_of_interests:
    messages: low
    blocks: normal

Field definitions:

  • storage: (optional) path to the storage. If omitted, the blockchain is stored in memory only.

  • logger: (optional) logger configuration,

    • verbosity: 0 - warning, 1 - info, 2 -debug, 3 and above - trace

    • format: log output format - plain or json.

    • output: log output - stderr, syslog (unix only) or journald (linux with systemd only, must be enabled during compilation)

  • rest: (optional) configuration of the rest endpoint.

    • listen: listen address

    • pkcs12: certificate file (optional)

    • prefix: (optional) api prefix

  • peer_2_peer: the P2P network settings

    • trusted_peers: (optional) the list of nodes to connect to in order to bootstrap the p2p topology (and bootstrap our local blockchain);

    • public_id: (optional) the public identifier send to the other nodes in the p2p network. If not set it will be randomly generated.

    • public_access: the address to listen from and accept connection from. This is the public address that will be distributed to other peers of the network that may find interest into participating to the blockchain dissemination with the node;

    • topics_of_interests: the different topics we are interested to hear about:

      • messages: notify other peers this node is interested about transactions typical setting for a non mining node: "low". For a stakepool: "high";

      • blocks: notify other peers this node is interested about new blocks. typical settings for a non mining node: "normal". For a stakepool: "high";

1.3.2. Starting the node

jormungandr --config config.yaml --genesis-block-hash 'abcdef987654321....'

The 'abcdef987654321…​.' part refers to the hash of the genesis, that should be given to you from one of the peers in the network you are connecting to.

In case you have the genesis file (for example, because you are creating the network) you can get this hash with jcli.

cat block-0 | jcli genesis hash

or, in case you only have the yaml file

cat genesis.yaml | jcli genesis encode | jcli genesis hash

1.4. REST

This section is unstable and will change.

It is possible to query the node via its REST Interface.

In the node configuration, one should do something like:

# ...

rest:
listen: "127.0.0.1:8443"
prefix: "api"

#...

This is the REST endpoint to talk to the node, to query blocks or send transaction.

It is possible to query the node stats with the following end point:

curl http://127.0.0.1:8443/api/v0/node/stats

Try it on the luceo endpoint

curl https://luceo.fractalide.org/v0/node/stats

The result may be:

{"blockRecvCnt":120,"txRecvCnt":92,"uptime":245}

2. General Concepts

This chapter covers the general concepts of the blockchain, and their application in the node, and is followed by the node organisation and the user interaction with it.

2.1. Blockchain concepts

2.1.1. Time

Slots represent the basic unit of time in a blockchain, at each slot a block might be present.

Consecutive slots are grouped into epochs, with an updateable size defined by the protocol.

2.1.2. Fragments

A Fragment is data representing about the blockchain, it includes updates to the protocol, transactions and certificate information.

2.1.3. Blocks

Blocks are the blockchain’s spine, they are safely and securely linked together into a chain, whilst grouping valid fragments together.

Blocks are composed of 2 parts:

  • The header

  • The content

The header securely links the content together with the blocks. The content is effectively a sequence of fragments.

2.1.4. Blockchain

A blockchain is defined by a set of rules that create blocks periodically. Rules can be changed on the fly in system updates, while others are hardcoded in the genesis block (first block of the blockchain).

              +-------+      +-------+
              |Genesis+<-----+Block 1+<--- ....
              |Header |      |Header |
              +---+---+      +---+---+
                  |              |
              +---v---+      +---v---+
              |Genesis|      |Block 1|
              |Content|      |Content|
              +-------+      +-------+

2.1.5. Consensus

Jormungandr currently supports the following consensus protocols:

  • Ouroboros BFT (OBFT)

  • Ouroboros Genesis-Praos

Ouroboros BFT is a simple Byzantine Fault Tolerant (BFT) protocol with known block makers that create and broadcast blocks onto the network in a round robin type fashion.

Ouroboros Genesis Praos is a proof of stake (PoS) protocol where block makers are selected via a sortition or lottery process. Each stake pool has a winning chance of being selected to create the next block proportional to their stake held. The sortitions are private or local to the stake pool, so other nodes don’t have no prior knowledge of who can create blocks.

2.1.6. Leadership

Leadership defines a set of nodes that check blocks are correctly created. New leadership is selected at the start of every epoch.

2.1.7. Leader

A leader is the randomly selected actor with the ability to create a block; In OBFT mode, the leader is just the owner of a cryptographic key, whereas in Genesis-Praos mode, the leader is a stake pool.

2.2. Node organisation

2.2.1. Secure Enclave

The secure enclave is designed to securely contain secret cryptographic material, it offers safe interfaces for the rest of the node to interact with.

2.2.2. Network

The node’s network consists of 3 components:

  • Intercommunication API (GRPC)

  • Public client API (REST)

  • Control client API (REST)

Intercommunication API (GRPC)

This interface is an binary interface using the protobuf format and GRPC standard. The protobuf files schema are available in the source code.

The interface is responsible to communicate with other nodes in the network:

  • block sending and receiving

  • fragments (transaction, certificates) broadcast

  • peer2peer gossip

Public API REST

This interface is for simple queries for clients like:

  • Wallet Client & Middleware

  • Analytics & Debugging tools

  • Explorer

it’s recommended for this interface to not be opened to the public.

Control API REST

This interface is not finished, but is a restricted via an ACL, it allows one to perform maintenance tasks on the process such as:

  • Node Shutdown

  • Load/Refresh/Retire cryptographic material

3. Staking with Jörmungandr

Here we will describe how to delegate stake to a stake pool allowing rewards to be collected.

Normal users shouldn’t need to setup a stakepool, thus please skip that section.

3.1. Registering your stake

Without a stake key you cannot participate in the consensus process. Generating this key allows one to have a place for their funds, participate in the protocol, claim stake, reap rewards and if one desires, setup a stakepool.

This key pair identifies you as a potential stake owner.

3.1.1. You stake key pair

It is preferable to use a key pair that is different from your wallet (for security reason). See the [jcli key] documentation to generate a new key pair of type Ed25519 or Ed25519Extended. For example:

$ jcli key generate --type=Ed25519Extended > stake_key.prv

The file stake_key.prv will contain your private key.

$ cat stake_key.prv | jcli key to-public > stake_key.pub

The file stake_key.pub will contain your public key.

3.2. Delegating your stake

Now that you have created your stake key you can choose to delegate your staking power to a stake pool.

3.2.1. How to create the delegation certificate

You will need your:

  • stake_key.pub file as created in stake key.

  • the Stake Pool ID: 32bytes identifying the stake pool you want to delegate your stake to.

$ jcli certificate new stake-delegation \
    ea830e5d9647af89a5e9a4d4089e6e855891a533316adf4a42b7bf1372389b74 \
    $(cat stake_key.pub) > stake_delegation.cert

3.2.2. How to sign your delegation certificate

Just like for the stake key certificate:

$ cat stake_delegation.cert| jcli certificate sign stake_key.prv | tee stake_delegation.cert
cert1q8rv4ccl54k99rtnm39...zr0

The output can now be added in the transaction and submitted to a node.

3.2.3. Submitting to a node

To jcli transaction add-certificate command can be used to add a certificate to a transaction in finalized state.

For example:

Note that in order to finalize a transaction, it should have both inputs and outputs.

...

jcli transaction finalize CHANGE_ADDRESS --fee-constant 5 --fee-coefficient 2 --fee-certificate 2 --staging tx

jcli transaction add-certificate $(cat stake_delegation.cert) --staging tx

...

The --fee-certificate flag indicates the cost of adding a certificate, used for computing the fees, it can be omitted if it is zero.

See transaction for more documentation on transaction creation.

3.3. Registering stake pool

There are a few bits of information important to running a stake pool:

  • Your NodeId: The global identifier. Wallets will delegate to your stake pool via this NodeId

  • Your VRF key pair: this is the cryptographic material used to participate in leader election;

  • Your KES key pair: this is the cryptographic material used to sign blocks with.

So in order to start your stake pool you will need to generate these objects.

3.4. The primitives

3.4.1. VRF key pair

jcli is used to generate your VRF key pair

$ jcli key generate --type=Curve25519_2HashDH > stake_pool_vrf.prv

stake_pool_vrf.prv file now contains the VRF private key.

$ cat stake_pool_vrf.prv | jcli key to-public > stake_pool_vrf.pub

3.4.2. KES key pair

Similar to above:

$ jcli key generate --type=SumEd25519_12 > stake_pool_kes.prv

stake_pool_kes.prv now contains your KES private key

$ cat stake_pool_kes.prv | jcli key to-public > stake_pool_kes.pub

3.4.3. Creating your stake pool certificate

The stakepool certificate is used to indicate to other stakepools you’re a block signer.

$ jcli certificate new stake-pool-registration \
    --kes-key $(cat stake_pool_kes.pub) \
    --vrf-key $(cat stake_pool_vrf.pub) \
    --serial 1010101010 > stake_pool.cert

Next, sign this certificate with the owner key:

$ cat stake_pool.cert | jcli certificate sign stake_key.prv | tee stake_pool.cert
cert1qsqqqqqqqqqqqqqqqqqqq0p5avfqp9tzusr26...cegxaz

Next, obtain your stake pool id (NodeId):

$ cat stake_pool.cert | jcli certificate get-stake-pool-id | tee stake_pool.id
ea830e5d9647af89a5e9a4d4089e6e855891a533316adf4a42b7bf1372389b74

4. JCLI

Generally interfacing with the node requires the use of JCLI, which is a command line application that contains all the cryptographic functions needed to work well. JCLI is mostly meant for developers and stake pool operators. It allows offline operations:

  • generating cryptographic materials for wallets and stake pools

  • creating addresses, transactions and certificates

  • prepare a new blockchain

and it allows simple interactions with the node:

  • query stats

  • send transactions and certificates

  • get raw blocks and UTxOs

  • etc

4.1. Key Subcommand

$ jcli key [subcommand]

These are the supported cryptographic keys and their uses

TYPE

USAGE

Ed25519

Signing algorithm for Ed25519 algorithm

Ed25519Bip32

Related to the HDWallet, Ed25519 Extended with chain code for derivation derivation

Ed25519Extended

Related to Ed25519Bip32 without the chain code

SumEd25519_12

For stake pool, necessary for the KES

Curve25519_2HashDH

For stake pool, necessary for the VRF

The command line parameter to generate a secret key:

$ jcli key generate --type=Ed25519
ed25519_sk1cvac48ddf2rpk9na94nv2zqhj74j0j8a99q33gsqdvalkrz6ar9srnhvmt

and the approach used to extract the associated public key:

$ echo ed25519_sk1cvac48ddf2rpk9na94nv2zqhj74j0j8a99q33gsqdvalkrz6ar9srnhvmt | jcli key to-public
ed25519_pk1z2ffur59cq7t806nc9y2g64wa60pg5m6e9cmrhxz9phppaxk5d4sn8nsqg

4.2. Address Subcommand

Jormungandr comes with a subcommand to create and manipulate addresses.

$ jcli address [subcommand]

For example; creating addresses from public keys for debugging addresses and for testing.

4.2.1. Display address info

To display an address and verify it is in a valid format you can utilise:

$ jcli address info ta1svy0mwwm7mdwcuj308aapjw6ra4c3e6cygd0f333nvtjzxg8ahdvxlswdf0
discrimination: testing
public key: ed25519e_pk1pr7mnklkmtk8y5tel0gvnksldwywwkpzrt6vvvvmzus3jpldmtpsx9rnmx

another example:

$ jcli address \
    info \
    ceo1qsy0mwwm7mdwcuj308aapjw6ra4c3e6cygd0f333nvtjzxg8ahdvxz8ah8dldkhvwfghn77se8dp76uguavzyxh5cccek9epryr7mkkr8n7kgx
discrimination: production
public key: ed25519e_pk1pr7mnklkmtk8y5tel0gvnksldwywwkpzrt6vvvvmzus3jpldmtpsx9rnmx
group key:  ed25519e_pk1pr7mnklkmtk8y5tel0gvnksldwywwkpzrt6vvvvmzus3jpldmtpsx9rnmx

4.2.2. Creating an address

Each subcommand can create an address for testing or production networks; simply add the flag --testing to the end of the command.

4.2.3. Address for UTxO

You can create a bootstrap era address by executing the following command.

$ jcli address \
    single ed25519e_pk1jnlhwdgzv3c9frknyv7twsv82su26qm30yfpdmvkzyjsdgw80mfqduaean
ca1qw207ae4qfj8q4yw6v3ned6psa2r3tgrw9u3y9hdjcgj2p4pcaldyukyka8

This kind of address is useful when running in the BFT era or if delegation is not desired.

4.2.4. Address for Account

Account are much simpler to use, they are needed to create reward account but it is also possible to utilise them as a wallet.

An Account address can do three things:

  • Send Luceo

  • Receive Luceo

  • Delegate staking rights to a stakepool

To create an account:

$ jcli address \
    account ed25519e_pk1c4yq3hflulynn8fef0hdq92579n3c49qxljasrl9dnuvcksk84gs9sqvc2
ca1qhz5szxa8lnujwva8997a5q42nckw8z55qm7tkq0u4k03nz6zc74ze780qe

4.3. Transaction Subcommand

Tooling for offline transaction creation and signing.

jcli transaction [subcommand]

There is a couple subcommands that can be used to:

  1. prepare a transaction:

    • new creates a new empty transaction;

    • add-input adds a utxo input

    • add-account adds an account

    • add-output adds a utxo output

  2. finalize the transaction for signing:

  3. create witnesses and add the witnesses:

    • make-witness

    • add-witness

  4. seal the transaction, ready to send to the blockchain

There are also functions to help decode and display the content information of a transaction:

  • info

  • id to get the Transaction ID of the transaction

  • to-message to get the hexadecimal encoded message, ready to send with cli rest message

4.3.1. Examples

Let’s say we have the following utxo

Field

Value

UTXO’s transaction ID

55762218e5737603e6d27d36c8aacf8fcd16406e820361a8ac65c7dc663f6d1c

UTXO’s output index

0

associated address

ca1q09u0nxmnfg7af8ycuygx57p5xgzmnmgtaeer9xun7hly6mlgt3pjyknplu

associated value

100

And we want to transfer 50 lu to the following address

ca1qvnr5pvt9e5p009strshxndrsx5etcentslp2rwj6csm8sfk24a2wlqtdj6

4.3.2. Create a staging area

jcli transaction new > tx

4.3.3. Adding a tx input

A tx input consists of the UTxO transaction id number, the UTxO output index and the amount, which indicates the amount of coin you want to send. The last parameter --staging <file> is also required as it’ll amend the contents of that file.

Example
jcli transaction add-input  55762218e5737603e6d27d36c8aacf8fcd16406e820361a8ac65c7dc663f6d1c 0 100 --staging tx

4.3.4. Adding a tx output

Adding a tx output consists of two parameters; the address to send to and the --staging <file> you’ll add the data to.

jcli transaction add-output  ca1qvnr5pvt9e5p009strshxndrsx5etcentslp2rwj6csm8sfk24a2wlqtdj650 --staging tx

4.3.5. Adding a fee and change address

We want to get the change in the same address that we are sending from (the associated address of the utxo). We also specify how to compute the fees. You can leave out the --fee-constant 5 --fee-coefficient 2 part if those are both 0.

jcli transaction finalize  ca1q09u0nxmnfg7af8ycuygx57p5xgzmnmgtaeer9xun7hly6mlgt3pjyknplu --fee-constant 5 --fee-coefficient 2 --staging tx

Now, if you run

jcli transaction info --fee-constant 5 --fee-coefficient 2 --staging tx

You should see something like this

Transaction `0df39a87d3f18a188b40ba8c203f85f37af665df229fb4821e477f6998864273' (finalizing)
  Input:   100
  Output:  89
  Fees:    11
  Balance: 0
 - 55762218e5737603e6d27d36c8aacf8fcd16406e820361a8ac65c7dc663f6d1c:0 100
 + ca1qvnr5pvt9e5p009strshxndrsx5etcentslp2rwj6csm8sfk24a2wlqtdj650 50
 + ca1q09u0nxmnfg7af8ycuygx57p5xgzmnmgtaeer9xun7hly6mlgt3pjyknplu 39

4.3.6. Signing the transaction

Making a witness

For signing the transaction a private key needs to be associated with a UTxO input address and the hash of the genesis block of the network you are connected to.

The genesis' hash is needed to ensure the transaction cannot be re-used in another blockchain and for security concerns in offline transaction signing, as we are signing the transaction for the specific blockchain started by a unique block0 hash.

The following command takes the private key in the key.prv file and creates a witness in a file named witness in the same directory.

jcli transaction make-witness --genesis-block-hash abcdef987654321... --type utxo txid --staging tx witness key.prv
Adding the witness
jcli transaction add-witness witness --staging tx

4.3.7. Send the transaction

jcli transaction seal --staging tx
jcli transaction to-message --staging tx > txmsg

Send it using the rest api

jcli rest v0 message post -f txmsg --host http://127.0.0.1:8443/api

4.3.8. Checking if the transaction was accepted

You can check if the transaction was accepted by checking the node logs, for example, if the transaction is accepted

jcli rest v0 message logs -h http://127.0.0.1:8443/api

- fragment_id: d6ef0b2148a51ed64531efc17978a527fd2d2584da1e344a35ad12bf5460a7e2
  last_updated_at: "2019-06-11T15:38:17.070162114Z"
  received_at: "2019-06-11T15:37:09.469101162Z"
  received_from: Rest
  status:
    InABlock: "4.707"

Where the InABlock status means that the transaction was accepted in the block with date "4.707".

The status here could also be:

Pending: if the transaction is received and is pending being added in the blockchain (or rejected).

or

Rejected: with an attached message of the reason the transaction was rejected.

4.4. Certificate Subcommand

Tooling for offline transaction creation

jcli certificate [subcommand]

4.4.1. Certificate builder

Builds a signed certificate.

The process can be split into discreet steps after the certificate is created.

jcli certificate new stake-pool-registration \
  --vrf-key <vrf-public-key> --kes-key <kes-public-key> \
  [--owner <owner-public-key>] \
  --serial <node-serial> \
  <output-file>

If the output-file is omitted, the result will be written to stdout. Once the certificate is ready you must sign it with the private keys of all the owners:

jcli certificate sign <key> <input-file> <output-file>

4.5. Genesis Subcommand

Tooling for working with a genesis file

4.5.1. Usage

jcli genesis [subcommand]

4.5.2. Subcommands

  • decode: Prints the YAML file corresponding to an encoded genesis block.

  • encode: Creates a genesis block of the blockchain from a given yaml file.

  • hash: Prints the block hash of the genesis

  • init: Creates a default Genesis file with appropriate documentation to help creating the YAML file

  • help

4.5.3. Examples

Encode a genesis file

jcli genesis encode --input genesis.yaml --output block-0.bin

or equivalently

cat genesis.yaml | jcli genesis encode > block-0.bin

Get the hash of an encoded genesis file

jcli genesis hash --input block-0.bin

4.6. REST Subcommand

Jormungandr comes with an HTTP client for manual communication with nodes.

4.6.1. Usage

jcli rest [subcommand]

4.6.2. Conventions

Many CLI commands have common arguments:

  • -h <addr> or --host <addr> - Node API address must always have http:// or https:// prefix. E.g. -h http://127.0.0.1, --host https://node.com:8443/luceo/api

  • --debug - Print additional debug information to stderr. The output format is intentionally undocumented and unstable

  • --output-format <format> - Format of output data. Possible values: json, yaml, default yaml. Any other value is treated as a custom format using values from output data structure. The syntax is Go text template.

4.6.3. Node statistics

Fetching node statistics

$ jcli rest v0 node stats get <options>

The options are

YAML printed on success

blockRecvCnt: 7 # Blocks received by node
txRecvCnt: 90   # Transactions received by node
uptime: 2101    # Node uptitme in seconds

4.6.4. Get the whole UTXO

Fetches whole UTXO

$ jcli rest v0 utxo get <options>

The options are

YAML printed on success

- in_idx: 0                                                                 # input index
  in_txid: 50f21ac6bd3f57f231c4bf9c5fff7c45e2529c4dffed68f92410dbf7647541f1 # input transaction hash in hex
  out_addr: ca1qvqsyqcyq5rqwzqfpg9scrgwpugpzysnzs23v9ccrydpk8qarc0jqxuzx4s  # output address in bech32
  out_value: 999999999                                                      # output value

4.6.5. Post a transaction

Posts a signed, hex-encoded transaction

$ jcli rest v0 message post <options>

The options are

  • -h <node_addr> - see conventions

  • --debug - see conventions

  • -f <file_path> or --file <file_path> - File containing hex-encoded transaction. If not provided, transaction will be read from stdin.

4.6.6. Get the message log

Get the node’s logs on the message pool. This will provide information on pending, rejected and/or transactions added to a block.

$ jcli rest v0 message logs <options>

The options are

YAML printed on success

- fragment_id: 7db6f91f3c92c0aef7b3dd497e9ea275229d2ab4dba6a1b30ce6b32db9c9c3b2 # hex-encoded fragment ID
  last_updated_at: 	2019-06-02T16:20:26.201000000Z                              # RFC3339 timestamp of last fragment status change
  received_at: 2019-06-02T16:20:26.201000000Z                                   # RFC3339 timestamp of fragment receivement
  received_from: Network,                                                       # how fragment was received
  status: Pending,                                                              # fragment status

received_from can be one of:

received_from: Rest     # fragment was received from node's REST API
received_from: Network  # fragment was received from the network

status can be one of:

status: Pending                 # fragment is pending
status:
  Rejected:                     # fragment was rejected
    reason: reason of rejection # cause
status:                         # fragment was included in a block
  InABlock: "6637.3"            # block epoch and slot ID formed as <epoch>.<slot_id>

4.6.7. Get the tip of the blockchain

Retrieves a hex-encoded ID of the blockchain tip

$ jcli rest v0 tip get <options>

The options are

4.6.8. Get a specific block

Retrieves a hex-encoded block with given ID

$ jcli rest v0 block `<block_id>` get `<options>`

<block_id> - hex-encoded block ID

The options are

4.6.9. Get the next block’s ID

Retrieves a list of hex-encoded IDs of descendants of block with given ID. Every list element is in separate line. The IDs are sorted from closest to farthest.

$ jcli rest v0 block `<block_id>` next-id get `<options>`

<block_id> - hex-encoded block ID

The options are

  • -h <node_addr> - see conventions

  • --debug - see conventions

  • -c <count> or --count <count> - Maximum number of IDs, must be between 1 and 100, default 1

4.6.10. Get the account state

Get an account’s state

$ jcli rest v0 account get <account-id> <options>

<account-id> - ID of an account, bech32-encoded

The options are

YAML printed on success

---
value: 257357,    # current balance of account in lovelace
counter: 4,       # number of transactions performed using this account

5. Advanced

This section is meant for advanced users and developers of the rust node. It explains how to start a new blockchain with limit settings, making it easier to start integration with wallets or exchanges and experimenting or testing new features.

5.1. The genesis file for your permissioned network

The genesis file is the file that allows you to create a new blockchain from block 0. It lays out the different parameter of your blockchain: the initial utxo, the start time, the slot duration time, etc…​

Example of a BFT genesis file with an initial address UTxO and an account UTxO. More info regarding starting a BFT blockchain here and regarding addresses there. You could also find information regarding the jcli genesis tooling.

You can generate a documented pre-generated genesis file:

jcli genesis init

There are multiple parts to a genesis file:

  • blockchain_configuration: this is a list of configuration parameters of the blockchain, some of which can be changed later via the update protocol;

  • initial:funds: the list of initial utxos (addresses and credited value);

5.1.1. Blockchain configuration options

option

format

description

block0_date

number

the official start time of the blockchain, in seconds since UNIX EPOCH

discrimination

string

production or test

block0_consensus

string

bft

slot_duration

number

the number of seconds between the creation of 2 blocks

epoch_stability_depth

number

allowed size of a fork (in number of block)

consensus_leader_ids

array

the list of the BFT leader at the beginning of the blockchain

max_number_of_transactions_per_block

number

the maximum number of transactions allowed in a block

bft_slots_ratio

number

placeholder, do not use

allow_account_creation

boolean

allow creating accounts without publishing certificate

linear_fee

object

linear fee settings, set the fee for transaction and certificate publishing

For more information about the BFT leaders in the genesis file, see Starting a BFT Blockchain

5.1.2. The initial options

Each entry can be one of 2 variants:

variant

format

description

fund

object

initial deposits present in the blockchain

cert

string

initial stakepool certificate

Example:

initial:
  - fund:
      address: <address>
      value: 10000
  - cert: <certificate>
  - fund:
      address: <another address>
      value: 1001

The fund format:

variant

format

description

address

string

can be a single address or an account address (if allow_account_creation is set to true)

value

number

assigned value

5.2. Starting a BFT node

BFT is an acronym for Byzantine Fault Tolerant (Ouroboros-BFT:A Simple Byzantine Fault Tolerant Consensus Protocol).

Jormungandr allows you to start a BFT blockchain fairly easily. This is designed for scenarios whereby expensive decentralised consensus isn’t needed, such as within a company or other types of centrally controlled environments. In BFT mode only a few blessed nodes have the ability to create blocks.

5.2.1. How does BFT work?

A given number of nodes (N) will each generate a key pair of type Ed25519 (see JCLI’s Keys).

Each node’s public key is added to the genesis.yaml file, thus every BFT node is aware of every other node. The genesis file is the single source of truth and will be used to generate the first block of the blockchain, that being; Block-0.

After the commencing of the blockchain, each BFT node takes turns, round robin fashion, creating blocks as ordered in the genesis.yaml file.

5.2.2. Example of genesis file

blockchain_configuration:
  block0_date: 1550822014
  discrimination: test
  block0_consensus: bft
  slots_per_epoch: 5
  slot_duration: 15
  epoch_stability_depth: 10
  consensus_genesis_praos_active_slot_coeff: 0.22
  consensus_leader_ids:
    - ed25519e_pk1k3wjgdcdcn23k6dwr0cyh88ad7a4ayenyxaherfazwy363pyy8wqppn7j3
    - ed25519e_pk13talprd9grgaqzs42mkm0x2xek5wf9mdf0eefdy8a6dk5grka2gstrp3en
  allow_account_creation: true
  linear_fees:
    constant: 0
    coefficient: 0
    certificate: 0
initial_funds:
  - address: ta1svy0mwwm7mdwcuj308aapjw6ra4c3e6cygd0f333nvtjzxg8ahdvxlswdf0
    value: 10000

In order to start your blockchain in BFT mode you need to be sure that:

  • consensus_leader_ids is non empty;

more information regarding the genesis file here.

5.2.3. Creating the block-0

jcli genesis encode --input genesis.yaml --output block-0.bin

This command will create (or replace) the Block 0 of the blockchain from the given genesis configuration file (genesis.yaml).

5.2.4. Starting the node

Now that the blockchain is initialized, you need to start your node.

Write you private key in a file on your HD:

$ cat node_secret.yaml
bft:
  signing_key: ed25519_sk1hpvne...

Configure your Node (config.yml) and run the following command:

$ jormungandr --genesis-block block-0.bin \
    --config example.config \
    --secret node_secret.yaml

It’s possible to use the flag --secret multiple times to run a node with multiple leaders.

5.2.5. Step by step to start the BFT node

  • Generate initial config

$ jcli genesis init > genesis.yaml`
  • Generate secret key, e.g.

$ jcli key generate --type=Ed25519 > key.prv
  • Put secret key in a file, e.g. node_secret.yaml as follows:

bft:
 signing_key: ed25519_sk1kppercsk06k03yk4qgea....
  • Generate public key out of previously generated key

$ cat key.prv |  jcli key to-public
  • Put generated public key in genesis.yaml under consensus_leader_ids:

  • Generate block =

$ jcli genesis encode --input genesis.yaml --output block-0.bin
  • Create config file and store it on your HD as node.config e.g. →

---
logger:
 verbosity: 4
 format: json
rest:
 listen: "127.0.0.1:8607"
 prefix: api
peer_2_peer:
 public_address: /ip4/127.0.0.1/tcp/8606
 topics_of_interests:
 messages: low
 blocks: normal

Start Jörmungandr node :

$ jormungandr --genesis-block block-0.bin --config node.config --secret node_secret.yaml

5.3. Starting a genesis praos blockchain

When creating a genesis praos blockchain one must take into consideration the the stake distribution of block-0.

In the context of Genesis/Praos the network is fully decentralized and it’s necessary to think ahead about initial stake pools and to make sure there is stake delegated to these stake pools.

In your genesis yaml file, make sure to set the following values to the appropriate values/desired values:

# The Blockchain Configuration defines the settings of the blockchain.
blockchain_configuration:
  block0_consensus: genesis
  bft_slots_ratio: 0
  consensus_genesis_praos_active_slot_coeff: 0.1
  kes_update_speed: 43200 # 12hours

block0_consensus set to genesis means you want to start a blockchain with genesis praos as the consensus layer.

bft_slots_ratio needs to be set to 0 (we don’t support composite modes between BFT mode and Genesis mode — yet).

consensus_genesis_praos_active_slot_coeff determines minimum stake required to try becoming slot leader, must be in range 0 exclusive and 1 inclusive.

5.3.1. Initial certificates

In the initial:certs field you will set an initial certificate. This is important to declare the stake pool and delegate stake to them. Otherwise no block will be ever created.

Remember that in this array order matters:

5.3.2. Stake pool registration

Now that you have a stake owner declared in the block-0 you can register a stake pool. Follow the instruction in registering a stake pool guide.

The owner key (the key you sign the stake pool registration certificate) is the secret key associated to a previously registered stake key.

5.3.3. Delegating stake

Now that there is both your stake key registered and there are stake pools available in the block0 you need to delegate to one of the stake pool. Follow the instruction in delegating stake.

And in the initial funds start adding the addresses. To create an address with delegation follow the instruction in JCLI’s address guide. Utilise the stake key registered previously as group address:

$ jcli address single $(cat wallet_key.pub) $(cat stake_key.pub)
ta1sjx4j3jwel94g0cgwzq9au7h6m8f5q3qnyh0gfnryl3xan6qnmjse3k2uv062mzj34eacjnxthxqv8fvdcn6f4xhxwa7ms729ak3gsl4qrq2mm

You will notice that addresses with delegation are longer (about twice longer) than address without delegation.

For example, the most minimal setting you may have is:

initial_certs:
  # register a stake key (K)
  - cert1q8rv4ccl54k99rtnm39xvhwvqcwjcm385n2dwvamahpu5tmdz3pl2qgqgp6lh9x0mngzy5krzw6fgkhkcvkjj3e64qveny82fgzlyfqf62hsfdup8us3h4rayn66wlt97u6e4syu07grm9sghxy3zdjm0quu8eqrdfpysq

  # register a stake pool (P), owner of the stake pool is the stake key (K)
  - cert1qsqqqqqqqqqqqqqqqqqqq0p5avfqp9tzusr26chayeddkkmdlap6tl23ceca8unsghc22tap8clhrzslkehdycufa4ywvqvs4u36zctw4ydtg7xagprfgz0vuujh3lgtxgfszqzqj4xk4sxxyg392p5nqz8s7ev5wna7eqz7ycsuas05mrupmdsfk0fqqudanew6c0nckf5tsp0lgnk8e8j0dpnxvjk2usn52vs8umr3qrccegxaz

  # delegate stake associated to stake key (K) to stake pool (P)
  - cert1q0rv4ccl54k99rtnm39xvhwvqcwjcm385n2dwvamahpu5tmdz3plt65rpewev3a03xj7nfx5pz0xap2cjxjnxvt2ma9y9dalzder3xm5qyqyq0lx05ggrws0ghuffqrg7scqzdsd665v4m7087eam5zvw4f26v2tsea3ujrxly243sgqkn42uttk5juvq78ajvfx9ttcmj05lfuwtq9qhdxzr0

initial_funds:
  # address without delegation
  - address: ta1swx4j3jwel94g0cgwzq9au7h6m8f5q3qnyh0gfnryl3xan6qnmjsczt057x
    value: 10000
  # address delegating to stake key (K)
  - address: ta1sjx4j3jwel94g0cgwzq9au7h6m8f5q3qnyh0gfnryl3xan6qnmjse3k2uv062mzj34eacjnxthxqv8fvdcn6f4xhxwa7ms729ak3gsl4qrq2mm
    value: 1000000

5.3.4. Starting the node

Now, for starting the node and be able to generate new blocks, you have to put your pool’s private keys and id in a file and start the node with the --secret filename parameter.


For example, if you follow the examples of the registering a stake pool guide.

You could create a file called poolsecret.yaml with the following content.

genesis:
  sig_key: Content of stake_pool_kes.prv file
  vrf_key: Content of stake_pool_vrf.prv file
  node_id: Content of stake_pool.id file

And you could start the node with this command

$ jormungandr --genesis-block block-0.bin --config config.yaml --secret poolsecret.yaml