What and Why of Hard Forks

Hard forks of the Monero chain are blockchains which have diverged from the main Monero chain at some block height. This divergence could be accidental due to some nodes not upgrading their client software in time. Or it could be intentional due to some developers forking the Monero client and introducing changes that are incompatible with the main Monero chain.

Data from four hard forks is available: Monero Original, MoneroV, Monero v7, and Monero v9. The first two were intentional hard forks and the last two are accidental ones. The table below shows the number of blocks in each of these forks. The accidental forks lasted only for a few blocks.

Fork NameFork blockBlocks in forkCommon key images
Monero Original1,546,000238,68286,685
MoneroV1,564,966146,3259,387
Monero v71,685,555291,061
Monero v91,788,000731,581

The same output can be spent in both the main Monero chain and a hard fork without violating the no double spending restriction. Whenever an output is spent, its key image is revealed. If the same key image appears in a Monero transaction and a hard fork transaction, the output being spent must be in the intersection of both transaction rings. If the transaction rings have an intersection size of one, the output being spent is identified.

This type of cross-chain analysis for Monero was first performed by Hinteregger et al. (2018). The instructions in the following chapters describe steps to perform their analysis followed by a final DM decomposition analysis. Hinteregger et al. had considered data from Monero Original and MoneroV. We add the two smaller hard forks which appeared after their work was published.

The last column in the above table shows the number of key images from each hard fork that also appeared on the main Monero chain (upto block height 2,530,000). If any of the outputs corresponding to these key images can be identified, they can be marked as mixins in all the other transactions they appear in. And the corresponding edges in these other transactions can be deleted before performing the DM decomposition analysis.

Why not use monero-blockchain-mark-spent-outputs?

Every Monero release contains a command-line tool called monero-blockchain-mark-spent-outputs which can be used to identify spent outputs. This tool takes a list of LMDB databases as input (see Download Hard Fork Data) and outputs a list of spent outputs. It implements the cascade attack, finds transactions which cause the zero-mixin effect as characterized by Wijaya et al., attempts to identify closed sets, and performs the cross-chain analysis proposed by Hinteregger et al. It is informally called the "blackball tool" in the Monero community.

This tool's goal is to help Monero users avoid spent outputs while choosing mixins for their transactions. Technically, we could have also used it to identify spent outputs. But we chose to identify the spent outputs without using this tool for the following two reasons.

  1. The tool fails to read the transactions in the MoneroV LMDB database. It outputs the error message Failed to parse transaction from blob.
  2. When the hard fork databases are given as input, it gives some errors with the message Rings for the same key image are disjoint.

The errors in point 2 can be explained as below.

  • Within a single Monero chain, an output is uniquely determined by the (amount, index) pair.
    • The amount corresponds to the number of coins associated with the output (zero for RingCT outputs).
    • The index is an incrementing counter which specifies the rank of the output in the list of all outputs corresponding to a particular amount (when the list is sorted by order of appearance on the blockchain).
  • An (amount, index) pair may be associated with different one-time addresses (public keys) on different Monero chains.
  • The monero-blockchain-mark-spent-outputs does not translate the (amount, index) pairs to one-time addresses (this was true at least until version v0.18.2.2, April 2023). So when a key image appears on two Monero chains, the corresponding transaction rings may have disjoint output indices.

To avoid such errors, our analysis uses RPC queries to the respective Monero clients to translate (amount, index) pairs to one-time addresses on each Monero chain before computing intersections.