Эта страница нужна, чтобы правильно читать rand_getSupply и рассуждать об эмиссии: откуда берётся RAND, куда он уходит и какое тождество делает предложение защищённой цепочки точным, хотя никто не может сложить её ноты.
Откуда RAND берётся и куда уходит
Защищённая цепочка не может сложить собственные деньги: значение ноты скрыто внутри её обязательства. Публичны только пересечения границы пула. Их пять видов, семь в цепочке с хранилищами программ (RPL-2, начиная с chain 20), а в chain 21 (fullnode v0.8.0, работает с 2026-10-12) свои пересечения добавляют мультиподписные счета и движок бессрочных контрактов:
| направление | пересечение | когда |
|---|---|---|
| внутрь | генезисная нота-депозит (alloc в файле genesis, раскрытая начиная с chain 14) | блок 0 |
| внутрь | выпуск из крана (Mint, до 100 RAND, подписан валидатором, несёт раскрытие ноты начиная с chain 14) | цепочки testnet с "faucet": true; начиная с chain 20 только на 16 кошельков из разрешённого списка, подпись одного из 18 минтеров, перечисленных в генезисе, не более 10 000 RAND за эпоху в 1 000 блоков |
| внутрь | Withdraw валидатора, выплачивающий освобождённый стейк и вознаграждения в ноту | в любое время |
| наружу | fee бандла: до chain 20 включительно целиком в rewards автора блока; в chain 21 нижняя граница уничтожается (burned, учитывается в base_fees_burned), а автору блока достаётся только чаевые (tip) | каждый бандл |
| наружу | burn_r бандла: Bond, сжигающий стейк в публичный stake валидатора | каждый bond |
| наружу | burn_r в Invoke: RAND, внесённый в публичное хранилище программы | начиная с chain 20 (v0.6.8) |
| внутрь | выплата из хранилища: RAND, который Invoke выплачивает из хранилища программы в виде ноты, сумма и получатель публичны | начиная с chain 20 (v0.6.8) |
| наружу | burn_r в CreateMultisig или MultisigDeposit: RAND, внесённый в публичный баланс мультиподписного счёта (multisig_rand_in) | chain 21, начиная с v0.8.0 |
| внутрь | ноты MultisigPay: RAND, который счёт выплачивает, сумма и получатель публичны (multisig_rand_out) | chain 21, начиная с v0.8.0 |
| наружу / внутрь | сжигание в PerpDeposit на торговый счёт и нота выплаты по бессрочному контракту, которую вычисляет цепочка (perps_rand_out, perps_rand_held); в chain 21 обеспечение единственного рынка — zUSD, поэтому эти счётчики там равны 0 | chain 21, начиная с v0.8.0 |
В цепочке, генезис которой задаёт tokens.burn_registration_fee, как у chain 21 (и у каждой цепочки начиная с 15), 1 RAND registration_fee за регистрацию токена тоже покидает пул через burned, но не попадает ни в одну запись реестра: он уничтожается, а автор блока оставляет себе только базовую часть бандла. В chain 21 раздел генезиса fees (burn_base и burn_floor) делает то же самое с рассчитанной нижней границей каждого бандла: с базовыми 0,001 RAND за перевод, с пословным слагаемым развёртывания, со слагаемыми газа и байтов вызова, с 0,01 RAND за сжигание через мост. Поэтому автор блока оставляет себе один tip, fee − floor, и fees_paid растёт именно на эту величину (Комиссии).
Рядом с пулом находится реестр валидаторов, в котором суммы хранятся в открытом виде, поскольку вес в консенсусе должен быть публичным. Стейк в реестре — настоящий RAND: его можно вывести из стейка и снять обратно в ноту. Начиная с chain 20 хранилища программ — второй публичный баланс рядом с ним: RAND, внесённый вызовом Invoke, остаётся там доступным для подсчёта, пока выплата не вернёт его в пул в виде ноты. Chain 21 добавляет третий — мультиподписные счета (Транзакции): баланс по каждому активу, который тратится пороговым набором ключей Dilithium2, инициализированный в генезисе казначейством фонда и открытый для CreateMultisig любого желающего за комиссию 1 RAND.
В chain 21 нет ни наград за блоки, ни инфляции. Первая запланированная эмиссия цепочки — субсидия за агрегацию блоков: убывающее количество нового RAND за каждый запечатанный блок, выплачиваемое агрегатору, чьё доказательство его покрывает; в chain 21 она не активна (Доказательства). В v0.8.0 есть и её форма, индексированная к доллару (fees.usd_subsidy, с ценой по курсу RAND/USD, за который набор валидаторов голосует через SetRandPrice), но chain 21 её не включает. Chain 21 — новая цепочка, запущенная 2026-10-12 (генезис вырезан в 10:22 UTC, 26 валидаторов переключились в 10:31 UTC), выделенная из chain 20 (fullnode v0.8.0, хардфорк). Её генезис выпустил 129 938,879078887 RAND: 26 000 в стейке у 26 генезисных валидаторов, 3 938,879078887 в семи нотах-депозитах (балансы семи кошельков операторов, перенесённые из chain 20 по скану пула chain 20 на высотах от 822 056 до 822 229) и 100 000 RAND новой эмиссии в казначействе фонда — мультиподписном счёте с порогом 2 из 3 подписантов (id d5fd1883…1958, rand_getSupply.multisig_issued). То, что другие кошельки держали в chain 20, около 36 025 RAND (35 040 RAND выпусков из крана разрешённым получателям, платежи пользователям), не переносилось, поскольку ноту нельзя воссоздать без адреса её владельца; не переносились и 2,606 RAND невыведенных вознаграждений валидаторов. Ещё три генезисные ноты несут 100,001999 zUSD моста (10, 89,002999 и 0,999), равные обеспечению, заблокированному на его четырёх backing-ах; это не RAND, и оно вне этого аудита. rand_getSupply в chain 21 показывает genesis_deposited 3 938 879 078 887 единиц, genesis_staked 26 000 000 000 000, multisig_issued 100 000 000 000 000 и invariant_holds: true (высота 2 178, 2026-10-12). Chain 20, вырезанная 2026-10-01 из состояния chain 19 на высоте 7 258, выпустила 31 184,243719258 RAND: те же 26 000 в стейке и 5 184,243719258 в семи нотах, рядом с двумя нотами по 99 zUSD. Chain 15, вырезанная 2026-09-26, выпустила в генезисе 23 000 RAND: 18 000 в стейке у 18 валидаторов и 5 000 в пяти нотах; восемь её более поздних валидаторов внесли стейк из существующих нот, и это ничего не выпустило. Каждый последующий выпуск из крана увеличивает выпущенную сумму, а каждая сожжённая комиссия её уменьшает.
Токены вне этого аудита
Перечисленные выше пересечения относятся к RAND. Токен RPL, переведённый через мост или нативный, никогда не пересекает границу RAND: индекс актива 0 зарезервирован за RAND, и реестр токенов его не выдаёт, поэтому BridgeAttest, TokenMint или начальный выпуск при регистрации всегда вносят ноту какого-то другого актива, а burn_a в BridgeBurn или TokenBurn всегда уничтожает такую ноту (сжигание RAND через burn_a отклоняется). fees_paid и burned считаются только по fee и burn_r бандла, а перевод токена внутри пула не двигает ни один счётчик, поскольку его актив даже не публичен. Начиная с chain 20 Invoke может также принять токен через burn_a: в хранилище программы (deposit), что оставляет его предложение неизменным, или уничтожить (burn), только для собственного токена программы. Комиссионные ноты моста (начиная с chain 20, 10 bps с каждого депозита и сжигания zUSD, на адрес казначейства) — это zUSD, а не RAND: выпущенные и обеспеченные, поэтому обеспечение депозита и предложение растут на валовую сумму, а при сжигании уменьшаются на amount − fee. Собственное предложение токена — публичный подсчёт реестра: rand_getTokenSupply возвращает total_supply и, для токена, переведённого через мост, locked каждого backing-а, которые в сумме дают его (Токены RPL). В chain 21 обеспечение движка бессрочных контрактов — тоже zUSD, поэтому депозиты и выплаты торгового счёта — это пересечения токенов, вне этого аудита (счётчики perps_rand_* существуют для рынка с обеспечением в RAND и равны 0).
Тождество аудита
Шесть монотонных счётчиков в единицах (1 RAND = 10⁹), три из них фиксируют уничтоженное, два относятся к хранилищам программ (начиная с chain 20), а в chain 21 добавляются пять для мультиподписных счетов и два для движка бессрочных контрактов:
| счётчик | что суммирует |
|---|---|
genesis_deposited | ноты-вклады alloc в файле генезиса |
genesis_staked | стейки, которыми генезис заполнил реестр |
faucet_minted | каждый принятый Mint |
withdraw_deposited | ноты, созданные принятыми Withdraw (по amount − 0.001 RAND каждая) |
fees_paid | комиссия каждого пакета |
burned | каждый burn_r пакета (стейк Bond, с chain 20 — вклад invoke в хранилище, на chain 21 — вклад при создании мультиподписи или пополнении), каждый сожжённый регистрационный сбор и на chain 21 — каждый сожжённый минимум комиссии |
slashed | конфискованные при слэшинге залоги агрегаторов (агрегация блоков; 0, пока она выключена) |
registration_fees_burned | регистрационные сборы, сожжённые согласно tokens.burn_registration_fee; входят и в burned |
base_fees_burned | минимумы комиссии пакетов, сожжённые согласно разделу fees генезиса (chain 21: burn_base вместе с burn_floor); входят и в burned; "0" на всех более ранних chain |
program_rand_out | ноты RAND, выплаченные хранилищами программ (RPL-2; 0 без раздела program_state) |
program_rand_held | RAND, которые хранилища всё ещё держат: burn_r каждого invoke за вычетом program_rand_out. Эти RAND попали туда через burned, поэтому это сторона хранилищ в том счётчике |
multisig_issued | генезисные балансы мультиподписных счетов (chain 21: казна в 100,000 RAND) — эмиссия, наряду с genesis_staked |
multisig_rand_in | каждый burn_r, внесённый CreateMultisig или MultisigDeposit; входит в burned, из пула в реестр |
multisig_rand_out | каждая нота RAND, созданная MultisigPay: стоимость, входящая в пул, наряду с withdraw_deposited |
multisig_base_out | базовые 0.001 RAND, которые платежи выплатили со счетов в rewards предлагающих: из реестра в реестр, не пересечение границы |
multisig_rand_held | issued + rand_in − rand_out − base_out: сколько держат счета, сторона реестра в total_supply |
perps_rand_out, perps_rand_held | та же пара для торговых счетов движка perps, для рынка с обеспечением в RAND; 0 на chain 21, чей рынок работает на zUSD |
pool_value = genesis_deposited + faucet_minted + withdraw_deposited
+ program_rand_out + multisig_rand_out + perps_rand_out − fees_paid − burned
register_total = Σ over the register of (stake + pending + rewards)
total_supply = pool_value + register_total + program_rand_held + multisig_rand_held + perps_rand_held
issued = genesis_deposited + genesis_staked + faucet_minted + multisig_issued
invariant: total_supply == issued − slashed − registration_fees_burned − base_fees_burned
pool_value — это вошедшее за вычетом вышедшего: то же число, что и сумма нот, которую никто не может вычислить. Базовые 0.001 RAND вывода не пересекают границу: они переходят из одной строки реестра в строку предлагающего, а границу пересекла только нота. Значение invariant_holds, равное false, означает ошибку консенсуса или повреждённую базу данных и никогда не бывает допустимым состоянием. Слагаемые программ, мультиподписи и perps равны нулю в chain без раздела program_state, multisig или perps, а base_fees_burned — без раздела fees, так что там тождество такое же, как в chain 19; на chain 20 действовали только слагаемые программ, а на chain 21 — все. Раздел vesting генезиса, которого не было ни в одной chain, добавил бы ещё один публичный реестр таким же образом (JSON-RPC).
Проследим один залог и один вывод 1,000 RAND в chain, где внесено 2,000 и поставлено в стейк 4,000:
| после | burned | withdraw_deposited | fees_paid | pool_value | register_total | total_supply |
|---|---|---|---|---|---|---|
| генезис | 0 | 0 | 0 | 2,000 | 4,000 | 6,000 |
| залог 1,000 (комиссия 0.001) | 1,000 | 0 | 0.001 | 999.999 | 5,000.001 | 6,000 |
| его снятие | 1,000 | 0 | 0.001 | 999.999 | 5,000.001 | 6,000 |
| его вывод 1,000 | 1,000 | 999.999 | 0.001 | 1,999.998 | 4,000.002 | 6,000 |
Как это читать
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", "base_fees_burned": "0",
"pool_value": "1999998000000", "register_total": "4000002000000",
"total_supply": "6000000000000", "invariant_holds": true }
Каждая сумма — десятичная строка в единицах, потому что число JSON не является точным целым за пределами 2⁵³. Полный объект содержит больше полей, чем показано здесь, среди них пара faucet по эпохам faucet_epoch и faucet_minted_in_epoch, которую chain 21 проверяет по своему бюджету, program_rand_out и program_rand_held (с v0.6.8), base_fees_burned, пять счётчиков multisig_* и два perps_* (с v0.8.0), а также четыре счётчика vesting_*, которые на chain 21 читаются как "0", поскольку в её генезисе нет раздела vesting (JSON-RPC). Эксплорер отдаёт тот же объект по GET /supply, а основные показатели — в GET /stats.
Насколько это точно
Для всего, что chain сделала сама, счётчики точны: каждый увеличивается в том месте кода, которое применяет действие, по публичным полям самого действия.
Две записи раньше держались на утверждении, а chain 14 превращает обе в проверки (аудит v3, POOL-1):
Mintкрана несёт раскрытие ноты. Помимоcmиamountдействие публикуетpk,timeиr. При допуске пересчитывается обязательство для(pk, no sender, amount, asset 0, time, r), и несовпадение отклоняется с ошибкойthe mint's commitment does not open to its published note and amount;timeпри этом должно попадать в окно пакета. Эмитент подписывает все семь полей в доменеrand-mint-2. Раньше валидатор мог опубликовать одну сумму, а запечатать ноту другой стоимости. Цена этого — публичностьpkвладельца ноты крана, как и выплаты при выводе; параметрыrand_mintне изменились.- Нота
allocгенезиса тоже несёт своё раскрытие. В chain с разделомtokensкаждая строка имеет вид{ cm, envelope, amount, opening: { pk, time, r } }, и узел пересчитывает обязательство — для asset 0, если только раскрытие не указываетassetтокена из списка, — и отвергает файл генезиса, в которомcmне совпадает. Вgenesis_depositedзасчитываются только строки asset 0. Непрозрачныйcmбыл единственным способом, которым автор генезиса мог поместить в пул необеспеченную ноту любого актива так, что никто не мог бы это проверить. Поэтому владелец и сумма ноты генезиса публичны по замыслу, как только файл опубликован; приватными остаются только момент и назначение её последующей траты.rand-node genesisвсегда записывает раскрытие.
В chain, выпущенной без раздела tokens, действует прежнее правило: genesis_deposited — сумма объявленных полей amount, принимаемая на веру из файла генезиса. Обе генезисные суммы входят в хэш генезиса, поэтому в любом случае все узлы с ними согласны.
Счётчики намеренно не входят в состояние консенсуса — корень состояния их не хэширует, — а rand-node verify --mode quick пересчитывает каждый из них, воспроизводя chain, и сообщает о расхождении, если сохранённый снимок не совпадает.