Coordinated forking

Introduction

As of release 1.2.0 the Radix node software introduces a coordinated forking mechanism.

This page contains an overview of how it works and how to use it from the node runner’s point of view.

What is a fork?

In a strict sense a fork is a situation when nodes in the network process the transactions using different sets of rules and they do not agree as to the output ledger state. As a result, the network splits - two or more groups of nodes can’t validate each other’s committed transactions.

We use the term fork more broadly: it refers to any update to the Radix Engine ruleset, even if it doesn’t result in a network split.

The node software consists of a set of fork configurations, each defining a set of rules for the Radix Engine. At any given time the node uses a single fork configuration and runs its corresponding engine ruleset.

Currently (up to the version 1.2.0) the Radix Olympia mainnet defines two fork configurations:

  • the genesis fork running throughout the epoch 1 - the initial network bootstrapping configuration for the first epoch

  • the olympia v1 fork starting at epoch 2 - the main olympia configuration, currently (as of v1.2.0) in use

Coordinated forking overview

Before release 1.2.0 the Radix engine could only fork (i.e. switch its configuration) at a fixed, predefined epochs. That’s how the genesis and olympia v1 forks were configured.

While this mechanism was good enough for bootstrapping, it is not the most reliable for introducing changes on a living network. Introducing a fork with a misjudged fixed epoch could potentially cause a liveness break if not enough validators have managed to upgrade their software on time.

To make the transition as smooth as possible, as of release 1.2.0, the Radix node software implements the coordinated forking mechanism, which allows the network to automatically switch to a newer configuration whenever the validators are ready.

Coordinated forking works by allowing the validators to signal their readiness to run the given fork configuration and only enact it when sufficient number of validators (by their stake) have signalled their readiness.

When a new software version is released with a new ruleset for the Radix engine, the corresponding fork configuration is a candidate fork. An upgraded node still runs the old set of rules and the switchover to the new candidate fork configuration is not scheduled at any specific epoch. The switchover happens when it has enough support from validators. When the fork occurs, any node running the upgraded version with the candidate fork will transition to the new set of rules automatically.

In order for the fork to actually occur, validators must first signal their readiness to switchover. This requires both running the upgraded software version, and explicitly signalling on ledger that the validator is ready. When enough validators (configurable, but no less than 2/3+1 of the total stake) signal their readiness and remain ready for a configurable number of consecutive epochs, the network switches over "forks". If a validator is running the new version, the validator will transition to the new ruleset if the fork occurs, regardless of whether it has signalled readiness. That said, a validator is strongly encouraged to signal readiness, so that the network will actually fork.

After this fork point, nodes not running the upgraded version may stop being able to ingest the ledger. Shortly after the fork, a new node version will be published which fixes the exact epoch of the fork into the node software as a fixed epoch fork.

I am a validator, how do I signal my readiness after upgrading?

First, make sure you’re running the latest Radix node software version (the newest version is available on the Github Releases page). You’ll only be able to vote for a candidate fork if it’s included in your binary.

Already running the latest version? Good. The recommended way to signal your readiness is to use the RadixNode CLI.

Using the RadixNode CLI

The signal-candidate-fork-readiness command will guide you through signalling your readiness. Just answer Yes when asked whether you want to signal.

radixnode api core signal-candidate-fork-readiness

The CLI is smart enough to know whether you need to signal or not. You won’t be bothered if there’s no candidate fork configuration to signal for of if your readiness has already been recorded.

Note that in order to signal your readiness you need your /key API enabled. Make sure you’ve got either the api.sign.enable property in your .config file or $RADIXDLT_SIGN_ENABLE env variable set to true.

Using the Core API

Internally, the readiness signalling mechanism is implemented in terms of "votes" for the candidate fork. Each reported readiness is stored on ledger as a candidate fork vote.

Use the Core API /key/vote endpoint to submit a vote transaction. The Core API will automatically inject the candidate fork vote information for whatever is the newest candidate fork configuration included in the software.

Below is an example POST /key/vote request payload

{
  "network_identifier": {
    "network": "mainnet"
  }
}

I am a validator, how do I know whether I need to signal a fork readiness?

As usual, the recommended way is to use the RadixNode CLI. The radixnode api core signal-candidate-fork-readiness command will tell you whether you need to signal your fork readiness.

Alternatively, there’s a fork_vote_status field in the /system/health API response. The return value of VOTE_REQUIRED indicates that a new fork configuration is present in the software for which the readiness hasen’t yet been signalled. If this is the value you’re receiving - signal your readiness! Otherwise, if the response is NO_ACTION_NEEDED you’re all good! There isn’t any new unsignalled candidate fork included in your software.

I have signalled a readiness but I want to rollback my node, what do I do?

If your rolled back node no longer contains a candidate fork for which you have signalled a readiness, the signal needs to be retracted.

You can also use the RadixNode CLI for this. Use the radixnode api core retract-candidate-fork-readiness-signal command to retract any readiness signals of yours.

Alternatively, the Core API /key/withdraw-vote endpoint can be used to retract a readiness signal without using the CLI.

Below is an example POST /key/withdraw-vote request payload

{
  "network_identifier": {
    "network": "mainnet"
  }
}

Note that in order to retract your readiness signal you need your /key API enabled. Make sure you’ve got either the api.sign.enable property in your .config file or $RADIXDLT_SIGN_ENABLE env variable set to true.