We continue our series in which we explore the inner workings of the Monero blockchain, and today’s text will be about RingCT (short for Ring Confidential Transactions), an algorithm that introduces an improved version of ring signatures which allows hiding the amount of funds being transferred.

There is still limited information available on the Internet about how it works, so we’ll try to fill in this gap. We’ll also try to figure out why the developers prefer it to classic CryptoNote’s ring signatures, and how this technology will evolve further.

This algorithm is one the most complex technologies used by the Monero blockchain, so reading this article may require some basic understanding of the blockchain’s specifics and elliptic curve cryptography. That’s why we strongly recommend reading the previous part of this series, Monero multisignatures explained, first, especially to those who might have missed it.

What is RingCT?

One possible way to attack the CryptoNote-based networks is through exploiting the information obtained from analysis of timestamps and value of any given transaction. This allows the attacker to significantly narrow the search scope when looking for relevant outputs. To protect users against this type of attacks, Monero introduced an anonymous transaction protocol that completely conceals the amount of funds transferred.

The idea itself isn’t new, of course. One of the first to propose it was Bitcoin Core developer Greg Maxwell, who described a similar algorithm in his article Confidential Transactions. The current implementation of RingCT is a modification of his original idea which, as the name implies, allows for ring signatures (there’s no way around them, obviously).

Among other things, RingCT solved the problem of so-called dust, the outputs of so little value that it wouldn’t be enough to cover even a minimum transaction fee, which used to make them nearly useless.

The feature was first implemented into the Monero protocol in January 2017 and became the only way to conduct transactions in September of the same year, after hard fork version 6.

RingCT employs several mechanisms allowing to conceal the transaction’s value at once: MLSAGs (short for Multilayered Linkable Spontaneous Anonymous Group signatures), the Pedersen commitment scheme, and range proofs.

In Monero, there are two main types of RingCT transactions: TypeSimple and TypeFull, where Simple is currently used when a transaction has multiple inputs, and Full is used when a transaction has a single input. The two types are a bit different in how the transactions are validated and how the signatures are assigned, but fundamentally they are the same. According to Zero to Monero, which is one of the best guides to the cryptocurrency, the very decision to limit TypeFull-transactions to one input was made in a hurry and this may very well change in the future.

MLSAGs

Let’s recall what the transaction inputs are. Each transaction simultaneously spends and generates a certain amount of funds. The generated funds are what we call outputs, and the outputs that were spent during the transaction become its inputs (be careful, it’s very easy to get confused here).

The main function of ring signatures of any type is that they allow for so-called ‘transaction mixing’. That means that when sending the funds to someone, the system creates several ‘fake’ outputs that also appear in the transaction, thus creating a ‘smokescreen’ so that no third party could track down the real sender. In other words, each potential input refers to multiple outputs, but only one of them will be really spent.

Now that a transaction has more than one input, we can represent its structure as a matrix, where the rows are the inputs, and the columns are the outputs to be mixed. To prove that the transaction spends its own outputs, i.e. knows the corresponding secret keys, all inputs are signed with a ring signature which guarantees that the signer knows the secret keys of all elements of one specific column.

This mechanism is classical for CryptoNote currencies and it effectively protects the sender’s anonymity while preventing double spending. However, in order to make transactions truly confidential, the Monero community decided to replace them with MLSAGs, which were based on a similar single-layered ring signature technology, LSAG, adapted to be used with multiple inputs.

The new type of signatures is called multi-layered precisely because through them you can sign several inputs at once, of which every input is ‘mixed’ with several others, meaning that the whole matrix is being signed, and not just one row. As we will see later, this also helps to keep signatures shorter.

Let’s take a look at how a ring signature is formed, using the example of a transaction that spends 2 real outputs and uses m–1random outputs for mixing. Here we denote the public keys of the outputs being spent by

, and the corresponding key images by

, respectively. Thus, we have a 2×m matrix. First, we need to calculate the so-called ‘challenges’ for each pair of outputs:

Fig. 1. Calculating challenges

We begin calculations with the outputs that would be spent, by using their public keys

and two random numbers

That gives us a set of values,

which we then use to calculate the ‘challenges’

for the next pair of outputs. We used different colors on the Fig. 1 to make it easier to understand which values are being substituted. All subsequent values ​​are calculated circle-wise according to the same formulas, so the ‘challenges’ for the real pair of outputs would be the last ones.

As we can see, in all columns, except for the one containing the real outputs, we now have randomly generated numbers

which we shall also use for the π-th column. Now let’s convert α into s:

Fig. 2. Restoring s

The signature itself is a sequence of all calculated values:

Fig. 3. Forming a MLSAG signature

These data are then added to the transaction.

As we can see, our MLSAG contains only one ‘challenge’, c₀, ensuring that the signature, which is quite long already, won’t be any longer. Now if we need to make sure that the transaction is legitimate we can restore the values of

The ring is now complete and the signature is verified.

In case of TypeFull transactions, one more row is added to the matrix, but now let’s move forward to the next component of RingCT. We’ll return to TypeFull later.

Pedersen Commitments

Commitment schemes are used in cryptography when any party needs to prove it has chosen a certain statement, number, or value (or chosen) while keeping it hidden to others, but retaining the ability to reveal it later. Imagine a group of people away from each other who make bets while playing dice. The first player rolls the dice, sees the result, then calculates the commitment and sends it to the others. Later, when the first person reveals what was the result, the others verify it using the commitment, making sure there was no cheating involved.

In Monero, commitments are used to conceal the values of transactions. The developers opted for the most common option, the Pedersen commitments. Interestingly enough, at first they suggested to conceal value by mixing alone, that is, by adding to any transaction a number of outputs of random amounts. It’s still questionable whether the current solution affects transaction size less.

In general, a commitment goes as follows:

where C is the value of the commitment itself, a is the value we’re going to hide, H is a fixed point on the elliptic curve (an additional generator), and xis some kind of a random mask, a randomly generated factor which adds another layer concealing the target value so that it would be harder to restore the original value by brute force.

When generating a new output, the wallet calculates a commitment for it, and when spending, it either takes the calculated value or recalculates it again, depending on the type of transaction.

RingCT simple

In case of TypeSimple RingCT transactions, when we need to guarantee that the sum of all created outputs is equal to the sum of all inputs (i.e. the transaction did not create money out of anywhere), we just check whether the sums of their respective commitments are the same, that is:

The commitment for the commission is calculated a little differently, without using a mask:

Where a is the publicly available amount of the commission.

This approach allows us to prove to anyone that we use the same amount without disclosing it.

To clarify things further, consider an example. Suppose a transaction spends two outputs (that is, they become inputs) of 10 and 5 XMR, respectively, while generating three outputs with a total value of 12 XMR, let’s say of 3, 4 and 5 XMR. At the same time, the sender sets the commission to be 3 XMR. Thus, the amount spent is equal to the amount generated plus the commission, that is, 15 XMR. Let’s try to calculate the commitments and the difference of their respective sums:

Fig. 4. The difference of the commitments’ respective sums

We need the sums to be the same, so the wallet generates a set of random numbers

while we calculate the remaining

With these masks, we can prove that we haven’t generated more funds than we have spent without revealing the exact amount. Nice, isn’t it?

RingCT full

In case of TypeFull transactions, everything gets a bit more complicated: the wallet does not recalculate the commitments for the inputs but uses the ones calculated when generating them. That means that the difference of their respective sums won’t be equal to zero, but instead:

where z is the difference of the masks related to the inputs and outputs. If we consider zG as a public key (which it de facto is), then z is a private key. Thus, we know both the public and the relevant private keys. With this data, we can apply them to the MLSAG ring signature alongside with the public keys of the outputs to be mixed:

Fig. 5. The data being signed by the ring signature

Thus, a valid ring signature guarantees that we know all private keys for one of the columns, and we can only know the private key related to the last row if the transaction does not generate more funds than it spends. By the way, that is the answer to the question why in this case we don’t need the difference of the commitments’ respective sums to be zero: if zG = 0, the column with the real outputs would be compromised.

But how does the recipient find out how much money was sent to him? That’s simple: the sender and the recipient exchange the keys using the Diffie-Hellman protocol and then use the transaction key and the recipient’s view key to calculate the hidden value.

Range proofs

Now, what will happen if we use a negative number as the sum of the commitments? This may result in creating extra coins! Such an outcome would be unacceptable, therefore we need to guarantee that the numbers we use are never negative (without disclosing these amounts, of course). In other words, we must prove that the sum belongs to the interval

To do this, the sum of each output is divided into binary digits, and then the commitments for each digit order number are calculated separately. It would be more clear if we consider an example.

Suppose that we create an output of 5 XMR, and all sums we get are small enough to fit into 4 bits (in real life it’s 64 bits). We calculate the commitments for each digit order number and the ‘total commitment’ for the whole amount:

Fig. 6. Bitwise commitments

Then each commitment is mixed with its surrogate

and each pair is signed with the Borromean ring signature, which is another type of ring signatures proposed by Greg Maxwell in 2015 (read more here):

Fig. 7. Signing the commitments

This method, which allows to ensure that all commitments use no amount beyond the interval of

is called ‘range proof’.

What’s next?

In the current implementation, range proofs consume a lot of space, 6,176 bytes per output. This leads to excessively large transactions and, therefore higher commissions. To limit the transaction size, Monero developers will switch from the Borromean signatures to Bulletproofs, a range proof mechanism without bitwise processing. By some estimates, that would reduce the range proof size by as much as 94%. This July, the technology was audited by Kudelski Security, which hasn’t found any significant shortcomings both in the technology itself and in its implementation. Bulletproofs are already in use within the test network, and it’s likely that the main network will adopt the feature with the next hard fork.

Later in this series, we will talk about other aspects of the Monero blockchain, such as wallets architecture and the libwallet library, as well as the network’s future prospects.

Please ask your questions in the comment section, suggest topics for new cryptocurrency-related articles, and subscribe to our blog to stay abreast of our upcoming events and valuable publications.