Utilisez cette page pour lire correctement rand_getSupply et raisonner sur l’émission : d’où vient le RAND, où il va, et l’identité qui rend exacte l’offre d’une chaîne blindée alors que personne ne peut additionner ses notes.
D’où vient le RAND et où il va
Une chaîne blindée ne peut pas additionner sa propre monnaie : la valeur d’une note réside dans son engagement. Ce qui est public, ce sont tous les passages de la frontière du pool. Il y en a cinq sortes, et sept sur une chaîne dotée de coffres de programme (RPL-2, chaîne 20) :
| sens | passage | quand |
|---|---|---|
| entrée | une note de dépôt de genèse (alloc dans le fichier de genèse, ouverte depuis la chaîne 14) | bloc 0 |
| entrée | un mint du faucet (Mint, jusqu’à 100 RAND, signé par un validateur, portant l’ouverture de la note depuis la chaîne 14) | chaînes testnet avec "faucet": true ; sur la chaîne 20, seulement pour 16 portefeuilles autorisés, signé par l’un des 18 minters listés dans la genèse, au plus 10 000 RAND par époque de 1 000 blocs |
| entrée | un Withdraw de validateur, qui verse la mise libérée et les récompenses dans une note | à tout moment |
| sortie | le fee d’un bundle, vers les rewards du proposeur du bloc | chaque bundle |
| sortie | le burn_r d’un bundle : un Bond qui brûle une mise vers le stake public d’un validateur | chaque bond |
| sortie | le burn_r d’un Invoke : du RAND déposé dans le coffre public d’un programme | chaîne 20, depuis v0.6.8 |
| entrée | un paiement de coffre : du RAND qu’un Invoke verse depuis le coffre d’un programme sous forme de note, montant et destinataire publics | chaîne 20, depuis v0.6.8 |
Sur une chaîne dont la genèse définit tokens.burn_registration_fee, comme celle de la chaîne 20, les 1 RAND de registration_fee d’un enregistrement de jeton quittent aussi le pool via burned, mais n’entrent dans aucune entrée du registre : ils sont détruits, et le proposeur ne garde que la base du bundle.
À côté du pool se trouve le registre des validateurs, qui détient des montants en clair parce que le poids de consensus doit être public. La mise dans le registre est du vrai RAND : elle peut être dé-liée puis retirée vers une note. Sur la chaîne 20, les coffres de programme forment un second solde public à ses côtés : le RAND qu’un invoke y dépose reste dénombrable jusqu’à ce qu’un paiement le renvoie au pool sous forme de note.
Il n’y a ni récompense de bloc ni inflation sur la chaîne 20. La première émission programmée de la chaîne est la subvention d’agrégation de blocs — une quantité décroissante de nouveau RAND par bloc scellé, versée à l’agrégateur dont la preuve le couvre — et elle n’est pas active sur la chaîne 20 (Preuves). La chaîne 20 est une chaîne neuve, en service depuis le 2026-10-01 à 06:17 UTC, issue de la chaîne 19 (fullnode v0.6.8, un hard fork). Sa genèse a émis 31 184,243719258 RAND : 26 000 misés sur les 26 validateurs de genèse et 5 184,243719258 dans sept notes de dépôt, les soldes des sept portefeuilles d’opérateur repris de la chaîne 19. Ce que les autres portefeuilles détenaient sur la chaîne 19, environ 519,9 RAND (mints du faucet vers des destinataires autorisés, paiements à des utilisateurs), n’a pas été repris, car une note ne peut être recréée sans l’adresse de son propriétaire ; les 0,499 RAND de récompenses de validateurs non retirées non plus. Deux autres notes de genèse, neuf au total, portent les 99 zUSD du bridge (10 et 89), qui ne sont pas du RAND et sortent de cet audit. rand_getSupply sur la chaîne 20 indique genesis_deposited 5 184 243 719 258 unités et invariant_holds: true (hauteur 3 037, 2026-10-01). La chaîne 19, issue le même jour d’un instantané de la chaîne 18 à la hauteur 141 935, a émis 31 294,644359629 RAND : les mêmes 26 000 misés et 5 294,644359629 dans sept notes, à côté d’une note de 10 zUSD. Chaque mint du faucet depuis s’ajoute au chiffre émis, et chaque frais d’enregistrement brûlé en retranche. La chaîne 15, issue le 2026-09-26, a émis 23 000 RAND à la genèse, dont 18 000 misés sur 18 validateurs et 5 000 dans cinq notes ; ses huit validateurs ultérieurs se sont liés à partir de notes existantes, ce qui n’a rien émis.
Les jetons sont hors de cet audit
Les passages ci-dessus sont ceux du RAND. Un jeton RPL, ponté ou natif, ne franchit jamais la frontière du RAND : l’indice d’actif 0 est réservé au RAND et le registre des jetons ne l’attribue jamais, de sorte qu’un BridgeAttest, un TokenMint ou le mint initial d’un enregistrement dépose toujours une note d’un autre actif, et que le burn_a d’un BridgeBurn ou d’un TokenBurn en détruit toujours une (du RAND brûlé via burn_a est refusé). fees_paid et burned se comptent à partir du seul fee et du seul burn_r d’un bundle, et un transfert de jeton à l’intérieur du pool ne fait bouger aucun compteur, puisque son actif n’est même pas public. Sur la chaîne 20, un Invoke peut aussi faire entrer un jeton par burn_a : dans le coffre du programme (deposit), ce qui laisse son offre inchangée, ou détruit (burn), pour le seul jeton du programme. Les notes de frais du bridge (chaîne 20, 10 bps de chaque dépôt et burn de zUSD, vers une adresse de trésorerie) sont du zUSD, jamais du RAND : émises et adossées, si bien que l’adossement d’un dépôt et l’offre varient du brut, et que ceux d’un burn baissent de amount − fee. L’offre propre d’un jeton est le décompte public du registre : rand_getTokenSupply renvoie total_supply et, pour un jeton ponté, le montant locked de chaque adossement, dont la somme lui est égale (Jetons RPL).
L’identité d’audit
Six compteurs monotones en unités (1 RAND = 10⁹), deux qui enregistrent ce qui a été détruit, et sur la chaîne 20 deux pour les coffres de programme :
| compteur | somme |
|---|---|
genesis_deposited | les notes de dépôt alloc du fichier de genèse |
genesis_staked | les mises dont la genèse a doté le registre |
faucet_minted | chaque Mint accepté |
withdraw_deposited | les notes créées par les Withdraw acceptés (amount − 0.001 RAND chacun) |
fees_paid | chaque frais de bundle |
burned | chaque burn_r de bundle (la mise d’un Bond et, sur la chaîne 20, le dépôt en coffre d’un invoke), et chaque frais d’enregistrement brûlé |
slashed | les cautions d’agrégateur sanctionnées (agrégation de blocs ; 0 tant qu’elle est désactivée) |
registration_fees_burned | les frais d’enregistrement brûlés sous tokens.burn_registration_fee, aussi inclus dans burned |
program_rand_out | les notes de RAND que les coffres de programme ont versées (RPL-2 ; 0 sans section program_state) |
program_rand_held | le RAND que les coffres détiennent encore : le burn_r de chaque invoke moins program_rand_out. Il y est arrivé par burned, c’est donc le côté coffres de ce compteur |
pool_value = genesis_deposited + faucet_minted + withdraw_deposited + program_rand_out − fees_paid − burned
register_total = Σ over the register of (stake + pending + rewards)
total_supply = pool_value + register_total + program_rand_held
issued = genesis_deposited + genesis_staked + faucet_minted
invariant: total_supply == issued − slashed − registration_fees_burned
pool_value est ce qui est entré moins ce qui est sorti — le même nombre que la somme des notes, que personne ne peut calculer. La base de 0,001 RAND d’un withdraw n’est pas un passage : elle passe d’une ligne du registre à celle du proposeur, et seule la note a franchi la frontière. Un invariant_holds à false est un bug de consensus ou une base de données endommagée, jamais un état légitime. Les deux termes de programme sont nuls sur une chaîne sans coffres de programme, l’identité y est donc celle de la chaîne 19. Une section vesting de genèse, qu’aucune chaîne n’a eue, ajouterait de la même manière un troisième registre public (JSON-RPC).
Suivie à travers un bond et un withdraw de 1 000 RAND sur une chaîne qui a déposé 2 000 et misé 4 000 :
| après | burned | withdraw_deposited | fees_paid | pool_value | register_total | total_supply |
|---|---|---|---|---|---|---|
| genèse | 0 | 0 | 0 | 2 000 | 4 000 | 6 000 |
| un bond de 1 000 (frais 0,001) | 1 000 | 0 | 0,001 | 999,999 | 5 000,001 | 6 000 |
| son unbond | 1 000 | 0 | 0,001 | 999,999 | 5 000,001 | 6 000 |
| son withdraw de 1 000 | 1 000 | 999,999 | 0,001 | 1 999,998 | 4 000,002 | 6 000 |
La lire
curl -s http://127.0.0.1:8545 -H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"rand_getSupply","params":[]}'
{ "height": 1998,
"genesis_deposited": "2000000000000", "genesis_staked": "4000000000000",
"faucet_minted": "0", "withdraw_deposited": "999999000000",
"fees_paid": "1000000", "burned": "1000000000000",
"slashed": "0", "registration_fees_burned": "0",
"pool_value": "1999998000000", "register_total": "4000002000000",
"total_supply": "6000000000000", "invariant_holds": true }
Chaque montant est une chaîne décimale d’unités, parce qu’un nombre JSON n’est pas un entier exact au-delà de 2⁵³. L’objet complet porte plus de champs que ceux montrés ici, dont la paire par époque du faucet, faucet_epoch et faucet_minted_in_epoch, que la chaîne 20 vérifie par rapport à son budget, program_rand_out et program_rand_held (depuis v0.6.8), et quatre compteurs vesting_* qui valent "0" sur la chaîne 20, dont la genèse n’a pas de section vesting (JSON-RPC). L’explorateur sert le même objet à GET /supply et les chiffres principaux dans GET /stats.
Quelle exactitude
Pour tout ce que la chaîne a fait elle-même, les compteurs sont exacts : chacun est incrémenté dans le chemin de code qui applique l’action, à partir des champs publics de l’action elle-même.
Deux entrées reposaient jusqu’ici sur une affirmation, et la chaîne 14 les transforme toutes deux en vérifications (audit v3, POOL-1) :
- Un
Mintdu faucet porte l’ouverture de la note. Outrecmetamount, l’action publiepk,timeetr. L’admission recalcule l’engagement de(pk, no sender, amount, asset 0, time, r)et refuse toute discordance avecthe mint's commitment does not open to its published note and amount, et contrainttimeà la fenêtre du bundle. Le minter signe les sept champs sous le domainerand-mint-2. Auparavant, un validateur pouvait publier un montant et sceller une note d’une valeur différente. Le coût est que la clépkdu propriétaire d’une note du faucet est publique, comme l’est le versement d’un retrait ; les paramètres derand_mintrestent inchangés. - Une note
allocde genesis porte aussi son ouverture. Sur une chaîne dotée d’une sectiontokens, chaque ligne est{ cm, envelope, amount, opening: { pk, time, r } }, et un nœud recalcule l’engagement, à l’asset 0 sauf si l’ouverture désigne l’assetd’un jeton listé, et refuse tout fichier de genesis dont lecmne correspond pas. Seules les lignes d’asset 0 comptent dansgenesis_deposited. Uncmopaque était l’unique moyen pour l’auteur d’un genesis d’introduire dans le pool une note sans contrepartie, de n’importe quel asset, sans que personne puisse le vérifier. Le propriétaire et le montant d’une note de genesis sont donc publics par conception dès la publication du fichier ; seuls le moment de sa dépense et sa destination restent privés.rand-node genesisécrit toujours l’ouverture.
Sur une chaîne créée sans section tokens, l’ancienne règle s’applique toujours : genesis_deposited est la somme des champs amount déclarés, reprise telle quelle du fichier de genesis. Les deux montants de genesis figurent dans le hash de genesis, de sorte que tous les nœuds s’accordent sur eux dans les deux cas.
Les compteurs ne font volontairement pas partie de l’état de consensus — la racine d’état ne les hache pas — et rand-node verify --mode quick les recalcule tous en rejouant la chaîne, et signale une discordance si l’instantané stocké diffère.