Rand Protocol
Документация
Основные понятия

Предложение

Как RAND выпускается и уничтожается, публичные пересечения границы пула, генезисная эмиссия chain 21, что сжигает chain 21 и инвариант аудита предложения, который проверяет каждый узел.

Эта страница нужна, чтобы правильно читать 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, поэтому эти счётчики там равны 0chain 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_heldRAND, которые хранилища всё ещё держат: 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_heldissued + 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:

послеburnedwithdraw_depositedfees_paidpool_valueregister_totaltotal_supply
генезис0002,0004,0006,000
залог 1,000 (комиссия 0.001)1,00000.001999.9995,000.0016,000
его снятие1,00000.001999.9995,000.0016,000
его вывод 1,0001,000999.9990.0011,999.9984,000.0026,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, и сообщает о расхождении, если сохранённый снимок не совпадает.

Последняя проверка по коммиту fullnode c0878c3f (chain 21) от 2026-10-12. Если код и эта страница расходятся, прав код; сообщите нам.