RingCT : vue d’ensemble
Comment adresses à usage unique, CLSAG, engagements et Bulletproofs+ s’assemblent dans une même transaction
RingCT (Ring Confidential Transactions) est le format de transaction de Monero depuis 2017. Chaque entrée = un anneau de 16 sorties + un engagement de pseudo-sortie + une signature CLSAG + une key image. Chaque sortie = une clé à usage unique + un engagement + un montant chiffré + un view tag. Par transaction : une preuve Bulletproofs+ et une vérification de l’équilibre.
Anatomie d’une transaction
Ce que vérifie un nœud, et comment
- La key image est nouvelle et appartient au bon sous-groupe (
l·I = 0) — pas de double dépense. - Tous les membres de l’anneau existent, ont plus de 10 blocs, et la taille de l’anneau est exactement 16.
- Équilibre :
Σ C̃ = Σ C_out + fee·H— égalité exacte de points. - Bulletproofs+ est valide — tous les montants des sorties sont dans
[0, 2⁶⁴). - CLSAG est valide pour chaque entrée — le signataire connaît la clé de l’une des 16 sorties, et cette même sortie a le même montant que la pseudo-sortie, et la key image lui appartient.
La vérification 5 est la plus astucieuse. CLSAG prouve la connaissance de deux secrets pour une même position de l’anneau :
Le premier dit « je possède la sortie », le second « la pseudo-sortie contient le même montant que l’entrée réelle ». Comme la position π est la même pour les deux (et cachée par l’anneau), on ne peut pas combiner le montant d’une sortie avec la clé d’une autre.
Qui voit quoi
| Observateur | Expéditeur | Destinataire | |
|---|---|---|---|
| Quelle entrée est la vraie | 1 sur 16 | le sait | 1 sur 16 |
| Adresse du destinataire | non | la connaît | la connaît (la sienne) |
| Montant de la sortie | non | le connaît | seulement ses propres sorties |
| Frais | oui | oui | oui |
| Nombre d’entrées et de sorties | oui | oui | oui |
| Moment (bloc) | oui | oui | oui |
Les trois dernières lignes sont des métadonnées que RingCT ne cache pas. Elles sous-tendent la plupart des heuristiques d’analyse.
Historique des versions de RingCT
| Type | Depuis | Ce qui a changé |
|---|---|---|
| RCTTypeFull / Simple | 2017 | MLSAG + preuves d’intervalle Borromean |
| RCTTypeBulletproof | 2018 | Bulletproofs au lieu de Borromean (transactions ~10× plus petites) |
| RCTTypeBulletproof2 | 2019 | Montant chiffré sur 8 octets au lieu de 32, masque dérivé de façon déterministe |
| RCTTypeCLSAG | 2020 | CLSAG au lieu de MLSAG |
| RCTTypeBulletproofPlus | 2022 | Bulletproofs+, anneau de 16, view tags |
| FCMP++ | prochain hard fork | anneaux remplacés par une preuve d’appartenance sur toute la chaîne |
Code : vérifier l’équilibre
Vous pouvez reproduire la vérification de l’équilibre sur une vraie transaction. Les pseudo-sorties se trouvent dans rctsig_prunable.pseudoOuts, les engagements des sorties dans rct_signatures.outPk :
// tx = transaction JSON from monerod (get_transactions, decode_as_json)
const sum = (pts) => pts.reduce((acc, p) => XMR.add(acc, XMR.decodePoint(p)), XMR.ZERO);
const lhs = sum(tx.rctsig_prunable.pseudoOuts);
const rhs = XMR.add(sum(tx.rct_signatures.outPk), XMR.mul(BigInt(tx.rct_signatures.txnFee), XMR.H));
console.log(XMR.eq(lhs, rhs)); // true — the balance holds, yet no amount is known
Faites la même expérience avec des montants inventés dans le calculateur d’engagements.