880 lines
53 KiB
Markdown
880 lines
53 KiB
Markdown
# TimeChain — Спецификация протокола Montana
|
||
|
||
**Версия:** 12.0.0 (2026-04-01)
|
||
|
||
## Определение
|
||
|
||
Децентрализованная сеть. Время — единственная реальная валюта. 1 секунда присутствия узла в сети = 1 Ɉ.
|
||
|
||
Консенсус: **Proof of Time (PoT)** — последовательное SHA-256 хэширование (VDF) как доказательство прошедшего времени. Временные окна возникают из вычислений.
|
||
|
||
Генезис: 09.01.2026 00:00:00 MSK.
|
||
|
||
---
|
||
|
||
## Криптография
|
||
|
||
Два примитива с разделёнными ролями:
|
||
|
||
- **SHA-256** — консенсус (Beacon VDF, Service VDF), адреса, Merkle-деревья, хэширование
|
||
- **FN-DSA-512** (selected NIST candidate, forthcoming FIPS 206) — подписи транзакционных блоков
|
||
|
||
SHA-256 обеспечивает квантовую устойчивость консенсуса: алгоритм Гровера сокращает безопасность с 256 до 128 бит. FN-DSA-512 обеспечивает математическую постквантовую устойчивость подписей на основе NTRU-решёток.
|
||
|
||
### Подписи — FN-DSA-512
|
||
|
||
Подпись на NTRU-решётках (Falcon-512). Stateless, многоразовая. Публичный ключ закрепляется за аккаунтом при создании и используется для всех последующих блоков.
|
||
|
||
| Компонент | Размер |
|
||
|-----------|--------|
|
||
| Приватный ключ | 1 281B |
|
||
| Публичный ключ | 897B |
|
||
| Подпись (padded) | 666B |
|
||
|
||
Поле suite_id в формате блока обеспечивает миграцию подписи без изменения модели состояния. Активация новой схемы требует protocol upgrade. Активная схема на момент запуска: FN-DSA-512.
|
||
|
||
### Адреса
|
||
|
||
Формат: `mt` + Base58(account_id + checksum).
|
||
|
||
Account_id = SHA-256("mt-account" || suite_id || pubkey). Стабильный идентификатор аккаунта. Смена ключа или схемы подписи выполняется через ChangeKey блок без изменения account_id — для этого account_id привязан к первому pubkey, а текущий ключ хранится в состоянии аккаунта.
|
||
|
||
---
|
||
|
||
## Account Chain (Block Lattice)
|
||
|
||
Каждый аккаунт имеет собственную цепочку блоков. Перевод — один блок в цепочке отправителя. Зачисление получателю — детерминированно после финализации IC/QC. Цепочки аккаунтов полностью независимы.
|
||
|
||
### Типы блоков
|
||
|
||
**OpenAccount** — создание аккаунта (один раз):
|
||
|
||
```
|
||
type 1B
|
||
suite_id 2B
|
||
account_id 32B
|
||
pubkey 897B ← FN-DSA-512, публикуется единожды
|
||
pending_root 32B ← Merkle root всех захваченных pending entries
|
||
balance 8B ← детерминированно = сумма захваченных entries (≥ ACCOUNT_RESERVE)
|
||
signature 666B
|
||
Итого: ~1 638B
|
||
```
|
||
|
||
**StateBlock** — перевод:
|
||
|
||
```
|
||
prev_hash 32B ← хэш предыдущего блока в цепочке аккаунта
|
||
account_id 32B
|
||
link 32B ← account_id получателя
|
||
link_amount 8B ← сумма перевода получателю
|
||
balance 8B ← абсолютный баланс отправителя после операции
|
||
flags 1B
|
||
signature 666B
|
||
Итого: ~779B
|
||
```
|
||
|
||
**ChangeKey** — смена ключа или схемы подписи:
|
||
|
||
```
|
||
prev_hash 32B
|
||
account_id 32B
|
||
new_suite_id 2B
|
||
new_pubkey 897B ← новый публичный ключ
|
||
signature 666B ← подписано старым ключом
|
||
Итого: ~1 629B
|
||
```
|
||
|
||
### Верификация баланса
|
||
|
||
Баланс в StateBlock абсолютный. StateBlock содержит поле balance (новый баланс отправителя после операции). Перевод содержит сумму в поле link_amount (8B, добавляется в формат StateBlock).
|
||
|
||
```
|
||
fee = prev_balance - new_balance - link_amount
|
||
```
|
||
|
||
Каждый узел проверяет: new_balance ≥ 0, link_amount > 0, fee ≥ min_fee.
|
||
|
||
### Комиссия
|
||
|
||
Комиссия вычисляется из трёх известных величин: prev_balance (из Account Table), new_balance и link_amount (из StateBlock). Минимум 1 mɈ. Размер min_fee адаптивный — рассчитывается по формуле на основе заполненности окон τ₁. Пользователь знает комиссию до отправки.
|
||
|
||
Победитель окна τ₂ получает сумму всех комиссий блоков в окне.
|
||
|
||
### Pending Transfers и OpenAccount
|
||
|
||
Отправка на несуществующий account_id создаёт pending entry в Pending Transfer Table:
|
||
|
||
```
|
||
Pending entry:
|
||
source_block_hash 32B
|
||
from_account_id 32B ← отправитель (для refund при expiry)
|
||
to_account_id 32B
|
||
amount 8B
|
||
expiry_τ₂ 4B ← дедлайн: N окон τ₂ после финализации
|
||
```
|
||
|
||
Баланс отправителя уменьшается сразу при финализации StateBlock. Средства хранятся в pending entry до открытия аккаунта получателем.
|
||
|
||
OpenAccount захватывает все pending entries адресованные данному account_id. Canonical rule: множество захваченных entries = все записи в Pending Transfer Table где `to_account_id == account_id`. Выбора нет — захватываются все или ни одна. pending_root в OpenAccount = Merkle root этого множества, отсортированного по (source_block_hash). balance = сумма amount всех захваченных entries.
|
||
|
||
Верификация OpenAccount в state transition:
|
||
|
||
1. Вычислить множество entries из Pending Transfer Table по to_account_id
|
||
2. Вычислить Merkle root множества → сравнить с pending_root в блоке
|
||
3. Вычислить сумму amount → сравнить с balance в блоке
|
||
4. Проверить balance ≥ ACCOUNT_RESERVE
|
||
5. Удалить все matching entries из Pending Transfer Table
|
||
6. Создать запись в Account Table
|
||
|
||
Автоматический возврат: если pending entry не захвачена OpenAccount до expiry_τ₂, средства возвращаются отправителю протокольно в state transition. Новая подпись отправителя не требуется.
|
||
|
||
### Account Reserve
|
||
|
||
ACCOUNT_RESERVE Ɉ — минимальная сумма для открытия аккаунта (параметр протокола). Защита от спама аккаунтов.
|
||
|
||
### Coinbase
|
||
|
||
Победитель τ₂ создаёт coinbase-блок в своей цепочке. Баланс увеличивается на сумму эмиссии + комиссии всех блоков окна.
|
||
|
||
Supply audit при финализации τ₂: суммарная эмиссия coinbase от генезиса сверяется с supply(height) из issuance schedule.
|
||
|
||
### Двойная трата
|
||
|
||
Каждый аккаунт имеет одну цепочку. Два блока с одним prev_hash = форк. Форк обнаруживается мгновенно. Разрешается QC (>2/3 активного веса голосует за каноничный блок).
|
||
|
||
---
|
||
|
||
## Состояние сети
|
||
|
||
Глобальное состояние = Account Table + Node Table + Pending Transfer Table + Expiry Queue.
|
||
|
||
```
|
||
Account Table (запись на аккаунт):
|
||
account_id 32B
|
||
balance 8B
|
||
frontier_hash 32B ← хэш последнего блока в цепочке
|
||
block_height 4B
|
||
suite_id 2B
|
||
current_pubkey 897B
|
||
|
||
Node Table (запись на узел):
|
||
node_id 32B ← SHA-256("mt-node" || node_pubkey), верифицируемо
|
||
node_pubkey 897B
|
||
suite_id 2B
|
||
chain_length 4B ← количество подписанных τ₂, weight = min(chain_length, MAX_WEIGHT)
|
||
cooldown_expires_τ₂ 4B ← 0 если cooldown пройден
|
||
checkpoint_equivocation 1B ← 0 или 1 (прогрессивный counter)
|
||
status 1B ← active | cooldown | suspended
|
||
|
||
Pending Transfer Table (запись на pending перевод):
|
||
source_block_hash 32B
|
||
from_account_id 32B ← для refund при expiry
|
||
to_account_id 32B
|
||
amount 8B
|
||
expiry_τ₂ 4B
|
||
|
||
Expiry Queue (индекс pending entries по сроку):
|
||
expiry_τ₂ 4B
|
||
entry_hash 32B
|
||
```
|
||
|
||
### State Root
|
||
|
||
Merkle-дерево глобального состояния. Четыре подкорня, каждый — Merkle root своей таблицы с явным порядком листьев:
|
||
|
||
```
|
||
State Root = SHA-256("mt-merkle-node" || account_root || node_root || pending_root || expiry_root)
|
||
|
||
Account Table Root: листья по account_id (лексикографически)
|
||
Node Table Root: листья по node_id (лексикографически)
|
||
Pending Transfer Root: листья по (to_account_id || from_account_id || source_block_hash) (лексикографически)
|
||
Expiry Queue Root: листья по (expiry_τ₂ big-endian 4B || entry_hash) (лексикографически)
|
||
|
||
active_set_root = Merkle root подмножества Node Table где status = active
|
||
и cooldown_expires_τ₂ < current_τ₂.
|
||
Детерминировано из Global State.
|
||
```
|
||
|
||
Все sort keys фиксированной длины. Побайтовое лексикографическое сравнение. Две реализации с одинаковыми данными строят одинаковое дерево и получают одинаковый State Root.
|
||
|
||
State Root коммитится в заголовке каждого финализированного proposal τ₂.
|
||
|
||
---
|
||
|
||
## Таймчейн
|
||
|
||
Три логических двигателя с односторонним потоком зависимостей: Beacon → Service → Execution.
|
||
|
||
### Beacon — глобальные часы протокола
|
||
|
||
Непрерывная последовательная SHA-256 цепочка. Общий источник случайности и ритм сети:
|
||
|
||
```
|
||
B_r = SHA-256^D(B_{r-1})
|
||
```
|
||
|
||
D — количество последовательных хэшей за один слот τ₁. Beacon продвигается по расписанию финализированных слотов. Для фиксированного индекса r значение B_r совпадает у всех честных узлов. Каждый узел вычисляет Beacon независимо — результат детерминирован.
|
||
|
||
Beacon не зависит от состояния, транзакций и поведения отдельных узлов.
|
||
|
||
### Service — персональный VDF узла
|
||
|
||
Доказательство непрерывного присутствия конкретного node_id. Якорится в Beacon каждый слот:
|
||
|
||
```
|
||
S_{i,s,0} = SHA-256(S_{i,s-1,m} || B_s || node_id_i)
|
||
S_{i,s,j+1} = SHA-256(S_{i,s,j}) для j = 0..m-1
|
||
```
|
||
|
||
Три компонента seed: предыдущий endpoint (непрерывность службы), значение Beacon (протокольное время), node_id (идентичность). m последовательных хэшей за слот — доказательство работы.
|
||
|
||
Service зависит от Beacon. Beacon не зависит от Service.
|
||
|
||
### Execution — содержимое блока
|
||
|
||
Приём, верификация execution objects и формирование канонического набора. Execution objects бывают четырёх типов:
|
||
|
||
| Тип | Описание | Валидация |
|
||
|-----|----------|-----------|
|
||
| StateBlock | Перевод средств | FN-DSA-512 подпись, баланс ≥ 0, prev_hash, link_amount > 0, fee ≥ min_fee |
|
||
| OpenAccount | Создание аккаунта | FN-DSA-512 подпись, pending_root, balance ≥ ACCOUNT_RESERVE |
|
||
| ChangeKey | Смена ключа | FN-DSA-512 подпись старым ключом, new_pubkey |
|
||
| NodeRegistration | Регистрация узла | FN-DSA-512 подпись, node_id уникален |
|
||
| EquivocationProof | Доказательство equivocation | Два конфликтующих подписанных сообщения от одного node_id |
|
||
|
||
Все типы проходят одинаковый IC pipeline: валидатор проверяет объект по правилам своего типа, включает H(object) в checkpoint body/blocks_root. IC достигается при >2/3 активного веса.
|
||
|
||
#### Inclusion Certificate (IC)
|
||
|
||
IC — пороговое свойство, не отдельный объект. Блок B имеет IC на слоте s при выполнении условия:
|
||
|
||
```
|
||
IC(B, s) = true
|
||
⟺
|
||
Σ weight(v), где существует slot s' ≤ s такой что
|
||
CP_{v,s'} валиден и H(B) доказуемо входит в blocks_root(CP_{v,s'})
|
||
>
|
||
2/3 × Σ weight(active_set)
|
||
```
|
||
|
||
Вес считается по уникальным валидаторам. Один валидатор — один голос, независимо от количества слотов в которых он подтвердил блок.
|
||
|
||
#### Data availability
|
||
|
||
Валидатор v включает H(obj) в checkpoint body только при выполнении условий:
|
||
|
||
1. Валидатор получил полный execution object
|
||
2. Проверил объект по правилам валидации его типа (таблица выше)
|
||
3. Включил H(obj) в checkpoint body и blocks_root
|
||
|
||
Data availability обеспечивается порогом IC: execution object набирает IC только если >2/3 активного веса независимо получили, проверили и включили его в свои чекпоинты. Один валидатор не может протолкнуть невидимый объект через IC. Отдельного наказания за data unavailability нет — отсутствие ответа на запрос не является криптографически доказуемым фактом.
|
||
|
||
#### Канонический набор
|
||
|
||
Канонический набор τ₂ = все блоки B где IC(B) достигнут до cutoff последнего слота окна. Канонический порядок: (earliest_certified_slot, H(B)). Детерминирован — каждый честный узел приходит к одному и тому же набору. Конфликты (форки аккаунтов) разрешаются правилом first valid in canonical order wins.
|
||
|
||
#### Proposer
|
||
|
||
Победитель лотереи вычисляет канонический набор детерминированно, добавляет coinbase. Содержимое proposal определено правилами IC и каноническим порядком. Свобода proposer: ноль. Отклонение от правил — невалидный proposal, переход ко второму месту. Любой узел независимо вычисляет тот же набор.
|
||
|
||
#### Верификация и финальность
|
||
|
||
Каждый валидатор независимо вычисляет канонический набор из собранных чекпоинтов. Если blocks_root в proposal совпадает с собственным вычислением → подписывает QC. Не совпадает → отклоняет.
|
||
|
||
QC на proposal header финализирует конкретный blocks_root и new_state_root. QC достаточен для финальности канонического набора. QC не является доказательством индивидуального IC каждого блока.
|
||
|
||
#### State transition
|
||
|
||
При финализации proposal state transition применяется атомарно в фиксированном порядке:
|
||
|
||
```
|
||
apply_proposal(state, proposal) → state':
|
||
|
||
Шаг 1: применить блоки канонического набора в порядке (earliest_certified_slot, H(B)).
|
||
StateBlock: обновить баланс отправителя.
|
||
Получатель существует → кредитовать баланс.
|
||
Получатель не существует → создать pending entry.
|
||
OpenAccount: захватить все pending entries для account_id
|
||
(включая созданные ранее на этом же шаге),
|
||
создать запись в Account Table.
|
||
ChangeKey: обновить pubkey и suite_id в Account Table.
|
||
NodeRegistration: создать запись в Node Table (chain_length=0, status=cooldown).
|
||
EquivocationProof: применить санкцию к node_id в Node Table
|
||
(checkpoint: counter++, cooldown / QC: status=suspended, chain_length=0).
|
||
|
||
Шаг 2: применить coinbase победителя.
|
||
|
||
Шаг 3: обновить chain_length.
|
||
Для каждого node_id опубликовавшего ≥ k валидных чекпоинтов в этом τ₂:
|
||
chain_length += 1 в Node Table.
|
||
Для узлов с cooldown_expires_τ₂ ≤ current_τ₂ и status = cooldown:
|
||
status = active.
|
||
|
||
Шаг 4: обработать expiry refunds.
|
||
Все pending entries где expiry_τ₂ ≤ current_τ₂
|
||
и не захваченные OpenAccount на шаге 1 →
|
||
вернуть amount на баланс from_account_id (поле в pending entry),
|
||
удалить entry из Pending Transfer Table и Expiry Queue.
|
||
|
||
Шаг 5: вычислить new_state_root.
|
||
```
|
||
|
||
Порядок детерминирован. Блоки первыми в каноническом порядке, coinbase вторым, chain_length третьим, expiry refunds последними. OpenAccount видит pending entries созданные ранее в том же τ₂. Каждый узел применяет одну и ту же последовательность шагов к одному и тому же набору блоков и получает один и тот же new_state_root. Отдельный receive-блок от получателя не требуется.
|
||
|
||
Execution зависит от Beacon и Service. Обратных зависимостей нет.
|
||
|
||
С ростом TPS сети дополнительные ядра подключаются для верификации блоков. Минимум для валидатора: 3 логических ядра (Beacon + Service + Execution). Верификация блоков аккаунтов полностью параллелизуется — цепочки аккаунтов независимы.
|
||
|
||
### Чекпоинт
|
||
|
||
Каждый валидатор в каждом слоте τ₁ публикует подписанный чекпоинт:
|
||
|
||
```
|
||
CheckpointHeader:
|
||
Sig_v(epoch, slot, B_s, S_{v,s,m}, blocks_root, block_count)
|
||
|
||
CheckpointBody:
|
||
block_hashes[] ← H(B) отсортированные лексикографически
|
||
(побайтовое сравнение), из которых строится blocks_root
|
||
```
|
||
|
||
CheckpointBody распространяется по P2P вместе с header. Без body чекпоинт неполон. blocks_root = Merkle root из block_hashes[] в заданном порядке. Membership proof: Merkle proof что H(obj) является листом в blocks_root.
|
||
|
||
Чекпоинт связывает протокольное время (B_s), доказательство службы (S_{v,s,m}) и проверенные execution objects (blocks_root + body) в одну подписанную аттестацию.
|
||
|
||
### QCVote
|
||
|
||
Голос узла за proposal при финализации τ₂:
|
||
|
||
```
|
||
QCVote:
|
||
node_id 32B
|
||
τ₂_index 4B
|
||
proposal_hash 32B ← SHA-256("mt-header" || proposal_header)
|
||
signature 666B ← FN-DSA-512, подписано node_pubkey
|
||
```
|
||
|
||
QC = набор QCVote с суммарным weight > 2/3 × Σ weight(active_set). EquivocationProof для qc_conflict содержит два QCVote с одинаковым (node_id, τ₂_index) и разным proposal_hash.
|
||
|
||
### Регистрация узла
|
||
|
||
Регистрация — каноническое событие в state transition. Новый узел появляется в сети через NodeRegistration:
|
||
|
||
```
|
||
NodeRegistration:
|
||
type 1B
|
||
suite_id 2B
|
||
node_pubkey 897B ← FN-DSA-512 ключ узла для подписи чекпоинтов и QC
|
||
signature 666B ← подписано node_pubkey
|
||
Итого: ~1 566B
|
||
```
|
||
|
||
node_id = SHA-256("mt-node" || node_pubkey). Вычисляется детерминированно из публичных данных. Верифицируемо любым узлом.
|
||
|
||
NodeRegistration проходит IC и включается в канонический набор τ₂ как execution object. При финализации state transition создаёт запись в Node Table: node_id, node_pubkey, suite_id, chain_length = 0, status = cooldown, cooldown_expires_τ₂ = current_τ₂ + cooldown (рассчитанный по формуле Adaptive Cooldown). checkpoint_equivocation = 0.
|
||
|
||
Счётчик new_registrations_in_τ₃ в формуле Adaptive Cooldown = количество финализированных NodeRegistration в данном периоде τ₃.
|
||
|
||
### Входной барьер — Adaptive Cooldown
|
||
|
||
Допуск к консенсусу определяется Adaptive Cooldown — динамическим входным периодом, чувствительным к темпу роста сети.
|
||
|
||
#### Формула
|
||
|
||
Скользящее окно из 3 последних τ₃ (42 дня). Темп роста — процент новых регистраций от количества активных узлов. Медиана трёх последних значений определяет норму:
|
||
|
||
```
|
||
growth_rate = new_registrations_in_τ₃ / active_nodes_at_start × 100%
|
||
median = median(growth_rate за 3 предыдущих τ₃)
|
||
excess = ((current_growth - median) / median) × 100%
|
||
|
||
excess ≤ 0%: cooldown = 7 дней
|
||
0% < excess ≤ 100%: cooldown = 7 + excess × 35 / 100
|
||
excess > 100%: cooldown = 42 дня
|
||
```
|
||
|
||
Минимум 7 дней. Максимум 42 дня (3 × τ₃).
|
||
|
||
Bootstrap: `effective_median = max(median, 1%)`, `effective_active = max(active_nodes, 10)`.
|
||
|
||
#### Асимметрия
|
||
|
||
Повышение cooldown — немедленное, без ограничений. Снижение — не быстрее 20% за τ₃. Атака поднимает барьер мгновенно. Возврат к норме занимает месяцы.
|
||
|
||
#### Реакция внутри τ₃ и фиксация
|
||
|
||
Cooldown для NodeRegistration вычисляется в момент финализации по одной переменной — effective_growth:
|
||
|
||
```
|
||
projected_growth = current_registrations / elapsed_fraction
|
||
elapsed_fraction = elapsed_slots / total_slots_in_τ₃
|
||
effective_growth = max(growth_rate_last_τ₃, projected_growth)
|
||
```
|
||
|
||
effective_growth подставляется в формулу cooldown. Счётчик current_registrations = количество финализированных NodeRegistration с начала текущего τ₃ в каноническом порядке (slot, H(obj)).
|
||
|
||
Cooldown закрепляется за узлом в момент финализации его NodeRegistration. Пересчёт не меняет cooldown уже зарегистрированным узлам.
|
||
|
||
#### Во время cooldown
|
||
|
||
Узел запускает Beacon + Service VDF сразу при регистрации. Валидирует блоки, ретранслирует данные, публикует чекпоинты. Узел усиливает сетевой слой и несёт стоимость допуска к консенсусу. Стоимость каждого Sybil-узла: 1 service-core непрерывно на весь период cooldown.
|
||
|
||
#### После cooldown
|
||
|
||
Вес начинается с 0 и растёт линейно с каждым подписанным τ₂. Работа во время cooldown полезна сети, но не конвертируется в консенсусный вес.
|
||
|
||
---
|
||
|
||
## Потоковая модель
|
||
|
||
Блоки аккаунтов текут непрерывно. Узел получает блок → проверяет подпись FN-DSA-512 и баланс → передаёт в P2P gossip. Время подтверждения определяется скоростью P2P-распространения (~2-5 секунд).
|
||
|
||
Блок включается в канонический набор τ₂ при получении Inclusion Certificate (>2/3 активного веса подтвердили через чекпоинты). Блоки не ожидают появления τ₁ или τ₂ — окна являются чекпоинтами, а не условиями приёма.
|
||
|
||
Цепочки аккаунтов полностью независимы. Блоки разных аккаунтов обрабатываются параллельно без конфликтов.
|
||
|
||
---
|
||
|
||
## Временные слои (τ)
|
||
|
||
```
|
||
τ₁ (≈60с) → τ₂ (10 × τ₁) → τ₃ (2016 × τ₂) → τ₄ (~104 × τ₃)
|
||
```
|
||
|
||
### τ₁ — Слот (≈60 секунд)
|
||
|
||
- Beacon продвигается на D хэшей
|
||
- Service VDF продвигается на m хэшей с якорем в текущем B_s
|
||
- Валидаторы публикуют подписанные чекпоинты CP_{i,s}
|
||
- Узлы обмениваются чекпоинтами и блоками аккаунтов по P2P
|
||
- Блоки набирают Inclusion Certificates
|
||
|
||
### τ₂ — Финализация и эмиссия (10 × τ₁ ≈ 10 минут)
|
||
|
||
- Active set (состав и веса участников) фиксируется в начале τ₂
|
||
- Канонический набор: все блоки с валидным IC до cutoff последнего слота
|
||
- Лотерея: `ticket_i = S_{i,final,m} / weight_i`, победитель = min(ticket_i) среди допущенных
|
||
- Победитель публикует proposal с заголовком:
|
||
|
||
```
|
||
Proposal header:
|
||
prev_qc_hash 32B
|
||
prev_state_root 32B ← State Root до применения блоков
|
||
blocks_root 32B ← Merkle root канонического набора
|
||
new_state_root 32B ← State Root после применения всех блоков
|
||
active_set_root 32B
|
||
beacon_value 32B
|
||
coinbase_hash 32B
|
||
```
|
||
|
||
- Финальность: QC на proposal header от >2/3 активного веса. Каждый валидатор применяет блоки детерминированно и проверяет new_state_root
|
||
- При финализации: state transition по фиксированному порядку (см. раздел «State transition» в Execution)
|
||
- Seed следующей эпохи: `seed_i = SHA-256(B_r || active_set_root_r || node_id_i)`
|
||
- Coinbase: вся эмиссия + все комиссии → победителю
|
||
- Supply audit: суммарная эмиссия coinbase от генезиса сверяется с supply(height) из issuance schedule
|
||
- Разрешение форков: приоритет ветки с наибольшим суммарным Beacon-доказательством
|
||
|
||
Beacon safety: компрометация значения Beacon требует нарушения свойства последовательности SHA-256 VDF или подделки finality certificate порогом >2/3 активного веса.
|
||
|
||
Beacon liveness: задержка продвижения Beacon требует блокировки finality порогом >1/3 активного веса.
|
||
|
||
### τ₃ — Адаптация (2016 × τ₂ ≈ 14 дней)
|
||
|
||
- Калибровка D и m: медиана слотовых интервалов сверяется с целевыми, цель τ₁ ≈ 60 секунд
|
||
- State Root коммитится в каждом τ₂ (в proposal header). State Root покрывает весь Global State: Account Table, Node Table, Pending Transfer Table, Expiry Queue. τ₃ фиксирует канонический State Root для Fast Sync
|
||
- Криптографическая амнезия: заголовки τ₂ и QC сохраняются навсегда — верифицируемая цепочка state commitments. Тела блоков аккаунтов, подписи FN-DSA-512, IC proofs и данные чекпоинтов удаляются после 8 × τ₃ (112 дней). Заголовки доказывают что конкретное состояние было закоммичено консенсусом; восстановление содержимого состояния требует snapshot или архива. Equivocation и slashing proofs по объектам старше 8 × τ₃ не принимаются — все споры разрешаются внутри окна
|
||
- Пересчёт параметров окна τ₁
|
||
- Пересчёт Adaptive Cooldown
|
||
|
||
### τ₄ — Эпоха (~104 × τ₃ ≈ 4 года)
|
||
|
||
- Потолок веса: MAX_WEIGHT = количество τ₂ в одном τ₄
|
||
- Эмиссия постоянна: 600 Ɉ/τ₂ в каждой эпохе
|
||
|
||
---
|
||
|
||
## Консенсус — Proof of Time (PoT)
|
||
|
||
### Три двигателя
|
||
|
||
**Beacon** — глобальные часы. Чистая VDF-цепочка `B_r = SHA-256^D(B_{r-1})`. Источник случайности для лотереи. Продвигается по расписанию финализированных слотов.
|
||
|
||
**Service** — персональный VDF. Якорится в Beacon каждый слот. Доказывает непрерывное присутствие node_id. Определяет вес и лотерейный билет.
|
||
|
||
**Execution** — содержимое блока. Канонический набор определяется Inclusion Certificate (>2/3 активного веса). Порядок детерминирован. Победитель собирает proposal механически.
|
||
|
||
Зависимости односторонние: Beacon → Service → Execution. Отказ в Execution не заражает случайность. Отказ конкретного узла в Service не заражает общий ритм.
|
||
|
||
### Стаж и вес
|
||
|
||
#### Определение
|
||
|
||
Вес узла — длина его непрерывной Service цепочки, измеренная в подписанных τ₂:
|
||
|
||
```
|
||
weight_i = min(chain_length_i, MAX_WEIGHT)
|
||
MAX_WEIGHT = количество τ₂ в одном τ₄ (~105 000)
|
||
```
|
||
|
||
Вес — единственная мера влияния узла в протоколе. Определяется только временем непрерывной службы.
|
||
|
||
#### Как растёт
|
||
|
||
Цепочка растёт на 1 за каждый τ₂ с засчитанным участием. Участие в τ₂ засчитывается при публикации не менее k валидных чекпоинтов из n слотов окна (k=8, n=10). Чекпоинт валиден при выполнении условий: подписан ключом node_id, содержит корректные epoch и slot, якорится в соответствующий Beacon slot, получен сетью до конца следующего слота.
|
||
|
||
#### Обрыв
|
||
|
||
Если узел за период τ₃ отработал менее 1613 из 2016 окон τ₂ — цепочка обрывается, weight = 0. Узел начинает копить длину заново. Adaptive Cooldown повторно не проходится (node_id уже зарегистрирован).
|
||
|
||
#### Три зоны
|
||
|
||
- **Cooldown (7-42 дня):** допуск закрыт, weight = 0, узел работает как валидатор и ретранслятор
|
||
- **После cooldown — 4 года:** weight растёт линейно с каждым подписанным τ₂
|
||
- **4+ года (≥ τ₄):** weight = MAX_WEIGHT, потолок
|
||
|
||
Потолок τ₄ предотвращает бесконечный рост преимущества ранних участников. Все цепочки старше 4 лет равны между собой.
|
||
|
||
#### На что влияет вес
|
||
|
||
Вес определяет три вещи:
|
||
|
||
**1. Лотерея.** Вероятность победы в τ₂ пропорциональна весу:
|
||
|
||
```
|
||
ticket_i = S_{i,final,m} / weight_i
|
||
winner = min(ticket_i)
|
||
P(node_i) = weight_i / Σ weight(all_nodes)
|
||
```
|
||
|
||
Больше вес → меньше ticket → выше шанс. Узел с weight = 0 не участвует в лотерее.
|
||
|
||
**2. Голосовая сила в консенсусе.** Inclusion Certificate и Quorum Certificate считаются по весу:
|
||
|
||
```
|
||
IC валиден: Σ weight(подтвердивших) > 2/3 × Σ weight(active_set)
|
||
QC валиден: Σ weight(подписавших) > 2/3 × Σ weight(active_set)
|
||
```
|
||
|
||
Голос узла в IC и QC пропорционален его weight.
|
||
|
||
**3. Допуск.** weight = 0 означает: узел участвует в сети (валидация, ретрансляция), но не участвует в лотерее и не имеет голосовой силы в IC/QC.
|
||
|
||
### Победитель τ₂
|
||
|
||
Победитель определяется после закрытия окна τ₂. Каждый узел раскрывает свой Service VDF endpoint. Минимальный ticket среди допущенных — победитель.
|
||
|
||
Победитель публикует proposal: канонический набор блоков аккаунтов (определён IC) + coinbase. Содержимое proposal детерминировано правилами IC и каноническим порядком. Свобода победителя: ноль.
|
||
|
||
Финальность возникает после QC на заголовок proposal от >2/3 активного веса.
|
||
|
||
### Верификация
|
||
|
||
Победитель публикует: `{node_id, Service checkpoints[], proposal}`.
|
||
|
||
Верификация Service VDF: пересчёт K сегментов параллельно. K ≈ 960. На C ядрах: ~(K/C) × t_segment секунд. 8 ядер → ~7.5 сек. 64 ядра → ~1 сек.
|
||
|
||
Верификация proposal: независимый расчёт канонического набора по IC и сравнение с proposal.
|
||
|
||
### Устойчивость
|
||
|
||
- **Proposer grinding** исключён: победитель не выбирает состав блока, канонический набор определяется IC (>2/3 активного веса)
|
||
- **Committee grinding** исключён: Beacon не зависит от состояния и транзакций, seed лотереи строится из Beacon
|
||
- **Node_id гриндинг** исключён: Adaptive Cooldown (7-42 дня), Beacon неизвестен при регистрации
|
||
- **Предвычисление** исключено: seed содержит текущее значение Beacon
|
||
- **Replay** исключён: Beacon уникален для каждого τ₂
|
||
- **Аппаратное преимущество** ограничено: последовательное хэширование масштабируется тактовой частотой и IPC, а не количеством ядер или бюджетом
|
||
- **Sybil-барьер**: Adaptive Cooldown (7-42 дня, асимметричный) + Service VDF (физическое ядро) + линейный рост веса от нуля
|
||
- **Аристократия** ограничена: потолок веса τ₄, после 4 лет все равны
|
||
|
||
### Разрешение конфликтов и санкции
|
||
|
||
Два класса нарушений. Пользовательские конфликты разрешаются протокольными правилами без санкций. Валидаторский equivocation — через аннулирование конфликтующих сообщений и санкции пропорциональные классу опасности.
|
||
|
||
#### Пользовательские конфликты
|
||
|
||
**Двойной блок аккаунта** (два блока с одним prev_hash): разрешается правилом first valid in canonical order wins. Без санкции.
|
||
|
||
**Невалидный proposal**: валидаторы отклоняют, QC не формируется, переход ко второму месту. Без санкции.
|
||
|
||
#### Валидаторский equivocation
|
||
|
||
При обнаружении конфликтующих подписанных сообщений от одного node_id: оба аннулируются. Вес узла в IC/QC за этот слот/τ₂ = 0.
|
||
|
||
Checkpoint equivocation — конфликт определяется по одинаковым (node_id, epoch, slot) с разным blocks_root или иным checkpoint payload:
|
||
|
||
```
|
||
1-й раз: cooldown 7 дней, вес сохранён
|
||
2-й раз: cooldown 42 дня, weight = 0
|
||
```
|
||
|
||
QC double vote — конфликт определяется по двум разным proposal_header_hash от одного node_id в одном τ₂:
|
||
|
||
```
|
||
1-й раз: сразу cooldown 42 дня, weight = 0
|
||
```
|
||
|
||
Санкция вступает в силу с следующего τ₂. Active set текущего τ₂ зафиксирован в его начале и не меняется до закрытия. Уже финализированный QC не откатывается ретроактивно — узел наказывается prospectively.
|
||
|
||
#### Equivocation proof
|
||
|
||
```
|
||
EquivocationProof:
|
||
type 1B ← checkpoint_conflict | qc_conflict
|
||
node_id 32B
|
||
evidence_a ← первое подписанное сообщение
|
||
evidence_b ← второе конфликтующее подписанное сообщение
|
||
```
|
||
|
||
Публикует любой узел обнаруживший конфликт. Верификация: оба сообщения подписаны одним node_id с одинаковыми координатами и разным содержимым. Подписи FN-DSA-512 криптографически верифицируемы. Подделка невозможна.
|
||
|
||
Proof включается в канонический набор τ₂. При финализации state transition применяет санкцию к node_id. Checkpoint equivocation counter в Node Table: 0 → cooldown 7 дней, 1 → cooldown 42 дня + chain_length = 0. Counter сбрасывается после chain_length = 0 и перезапуска цепочки. QC double vote: сразу chain_length = 0 + cooldown 42 дня + status = suspended.
|
||
|
||
---
|
||
|
||
## Адреса и переводы
|
||
|
||
### Полный флоу перевода
|
||
|
||
```
|
||
1. Боб: кошелёк создаёт аккаунт → account_id (постоянный адрес)
|
||
2. Боб → Алисе: "отправь на mt4ZGfe..." (account_id)
|
||
3. Алиса формирует StateBlock в своей цепочке:
|
||
prev_hash: хэш её предыдущего блока
|
||
link: account_id Боба
|
||
link_amount: 50 Ɉ
|
||
balance: 49.999 Ɉ (100 - 50 - 0.001 fee)
|
||
4. Алиса подписывает FN-DSA-512
|
||
5. Алиса рассылает блок узлам сети
|
||
6. Каждый узел проверяет:
|
||
FN-DSA-512 подпись валидна для pubkey Алисы ✓
|
||
prev_hash совпадает с frontier Алисы ✓
|
||
fee = 100 - 49.999 - 50 = 0.001 Ɉ ≥ min_fee ✓
|
||
balance ≥ 0 ✓
|
||
link_amount > 0 ✓
|
||
7. Блок распространяется через P2P gossip
|
||
8. Блок получает IC (>2/3 валидаторов подтвердили в чекпоинтах)
|
||
9. При финализации τ₂:
|
||
Баланс Алисы: 50 Ɉ (из StateBlock)
|
||
Баланс Боба: увеличен на 50 Ɉ (детерминированно)
|
||
```
|
||
|
||
### Баланс
|
||
|
||
Баланс аккаунта — одно число в таблице аккаунтов. Обновляется при финализации: исходящие переводы (из StateBlock отправителя) и входящие зачисления (детерминированно по финализированным блокам).
|
||
|
||
Бэкап = seed (для деривации приватного ключа FN-DSA-512).
|
||
|
||
---
|
||
|
||
## Эмиссия
|
||
|
||
### Единица
|
||
|
||
1 секунда Montana = 1 $MONT = 1 Ɉ = 1 000 mɈ = 1 000 000 μɈ = 1 000 000 000 nɈ
|
||
|
||
Точность: 9 знаков после запятой (наносекунда). Все расчёты эмиссии в nɈ (целочисленная арифметика, без плавающей точки).
|
||
|
||
### Issuance schedule
|
||
|
||
Одна секунда протокольного времени порождает одну монету. С первого блока и навсегда.
|
||
|
||
| Параметр | Значение |
|
||
|----------|----------|
|
||
| Генезис | 09.01.2026 00:00:00 MSK |
|
||
| REWARD | 600 000 000 000 nɈ (600 Ɉ) |
|
||
|
||
### Функция награды
|
||
|
||
```
|
||
reward(height) = 600_000_000_000 nɈ
|
||
```
|
||
|
||
Каждое окно τ₂ длится 600 секунд и создаёт ровно 600 Ɉ. Без халвингов, без фаз, без исключений. Одна константа на весь горизонт существования сети.
|
||
|
||
### Supply audit
|
||
|
||
```
|
||
supply(height) = 600_000_000_000 × (height + 1) nɈ
|
||
```
|
||
|
||
Одно умножение. Проверяемо каждым узлом в каждом τ₂. O(1).
|
||
|
||
### Инфляция
|
||
|
||
Supply растёт линейно. Инфляция снижается асимптотически к нулю — константная эмиссия делится на растущий supply:
|
||
|
||
```
|
||
Год 1: 100%
|
||
Год 2: 50%
|
||
Год 5: 20%
|
||
Год 10: 10%
|
||
Год 50: 2%
|
||
Год 100: 1%
|
||
Год 1000: 0.1%
|
||
```
|
||
|
||
### Bootstrap
|
||
|
||
Ранние участники получают непропорционально большую долю через вероятность лотереи, а не через повышенную награду. При 10 узлах каждый побеждает примерно раз в 100 минут. При 100 000 — раз в 2 года. Bootstrap встроен в математику лотереи, а не в расписание эмиссии.
|
||
|
||
### Распределение
|
||
|
||
Победитель τ₂ получает всю эмиссию + все комиссии окна через coinbase-блок в своей цепочке. Одно правило. Неизменно с генезиса.
|
||
|
||
Базовый бюджет эмиссии постоянный в единицах протокола: 600 Ɉ/τ₂ + комиссии. Реальный бюджет безопасности в покупательной способности зависит от рынка.
|
||
|
||
1 Ɉ = 1 секунда описывает скорость эмиссии. Не ценовой peg, не гарантия покупательной способности.
|
||
|
||
---
|
||
|
||
## Пропускная способность
|
||
|
||
Размер StateBlock: ~779B.
|
||
|
||
| Канал узла | TPS |
|
||
|-----------|-----|
|
||
| 10 Mbps | ~1 620 |
|
||
| 100 Mbps | ~16 200 |
|
||
| 1 Gbps | ~162 000 |
|
||
|
||
### Адаптивный размер окна
|
||
|
||
Пересчёт в τ₃:
|
||
|
||
- Заполненность > 80% → увеличение размера окна
|
||
- Заполненность < 20% → уменьшение размера окна
|
||
- Шаг: ±20% за τ₃
|
||
- Диапазон: 1 MB — 100 MB
|
||
|
||
---
|
||
|
||
## Хранение
|
||
|
||
### Состояние (Global State)
|
||
|
||
| Аккаунтов | Размер таблицы |
|
||
|-----------|---------------|
|
||
| 1M | ~1 GB |
|
||
| 10M | ~10 GB |
|
||
| 100M | ~100 GB |
|
||
|
||
### История блоков
|
||
|
||
| TPS | Архивный (20 лет) | Полный (112 дней) | Pruned | Light |
|
||
|-----|-------------------|-------------------|--------|-------|
|
||
| 7 | ~3.4 TB | ~42 GB | Account Table | Account Table |
|
||
| 100 | ~49 TB | ~600 GB | Account Table | Account Table |
|
||
| 1000 | ~486 TB | ~5.9 TB | Account Table | Account Table |
|
||
|
||
| Тип узла | Содержимое | Лотерея |
|
||
|----------|-----------|---------|
|
||
| Полный | Скользящее окно 8 × τ₃ + Global State + заголовки | weight × 1 |
|
||
| Архивный | Полная история от генезиса | weight × 1 |
|
||
| Pruned | Global State + заголовки | Наблюдатель |
|
||
| Light | Global State | Наблюдатель |
|
||
|
||
Узел самостоятельно выбирает тип. Участие в лотерее: полный или архивный узел. Вес определяется только временем непрерывной службы. Тип узла на вес не влияет. Архивный узел — добровольная роль. Протокол хранит доказательства (заголовки τ₂ с State Root навсегда). Рынок хранит исторические данные (тела блоков). Консенсус не зависит от архивов.
|
||
|
||
### Fast Sync (новый узел)
|
||
|
||
1. Цепочка заголовков τ₂ от генезиса — проверка Beacon-цепочки и QC (мегабайты)
|
||
2. State Root из последнего τ₃ (покрывает весь Global State)
|
||
3. Global State snapshot от пиров: каноническая сериализация всех листьев Merkle-дерева состояния (Account Table + Pending Transfer Table + Cooldown Registry + Expiry Queue). Верификация: пересчёт Merkle root из полученных листьев, сравнение с State Root из заголовка τ₃. `MerkleRoot(snapshot_leaves) == state_root_from_header`
|
||
4. Блоки аккаунтов за последние 112 дней (скользящее окно)
|
||
5. Узел синхронизирован и готов к участию
|
||
|
||
Заголовки доказывают цепочку state commitments. Snapshot восстанавливает содержимое состояния через пересчёт Merkle root. Блоки скользящего окна обеспечивают верификацию недавних переходов.
|
||
|
||
---
|
||
|
||
## Ключи
|
||
|
||
```
|
||
seed
|
||
├── Аккаунт: FN-DSA-512 keypair → account_id = SHA-256("mt-account" || suite_id || account_pubkey)
|
||
└── Узел: FN-DSA-512 keypair → node_id = SHA-256("mt-node" || node_pubkey)
|
||
```
|
||
|
||
Один seed порождает два FN-DSA-512 keypair: для аккаунта (подпись блоков) и для узла (подпись чекпоинтов, QC). account_id и node_id выводятся из публичных ключей, верифицируемы без знания seed. Бэкап = seed.
|
||
|
||
---
|
||
|
||
## Криптографическая реализация
|
||
|
||
### Primitive layer
|
||
|
||
Собственная реализация криптографических примитивов запрещена. Только audited библиотеки с constant-time гарантиями и опубликованными test vectors.
|
||
|
||
| Примитив | Стандарт | Роль |
|
||
|----------|----------|------|
|
||
| SHA-256 | FIPS 180-4 | Beacon VDF, Service VDF, адреса, Merkle-деревья |
|
||
| FN-DSA-512 | Selected NIST candidate, forthcoming FIPS 206 | Подписи блоков аккаунтов |
|
||
|
||
### Consensus encoding layer
|
||
|
||
Консенсусно-критическая поверхность: каноническая сериализация, Merkle layout и domain separation. Разная сериализация одного объекта = разный хэш = форк. Требования:
|
||
|
||
- Fixed binary encoding для каждого консенсусного объекта
|
||
- Length-prefix кодирование полей, фиксированный endianness (little-endian)
|
||
- Domain separation для всех хэшей:
|
||
|
||
| Домен | Контекст |
|
||
|-------|----------|
|
||
| `mt-block` | Хэширование блоков аккаунтов |
|
||
| `mt-header` | Хэширование proposal headers |
|
||
| `mt-account` | Деривация account_id |
|
||
| `mt-pending` | Хэширование pending entries |
|
||
| `mt-merkle-leaf` | Листья Merkle-деревьев |
|
||
| `mt-merkle-node` | Внутренние узлы Merkle-деревьев |
|
||
| `mt-checkpoint` | Хэширование чекпоинтов |
|
||
| `mt-beacon` | Beacon VDF seed |
|
||
| `mt-service` | Service VDF seed |
|
||
| `mt-equivocation` | Хэширование equivocation proofs |
|
||
|
||
- Альтернативные сериализации запрещены
|
||
- Test vectors для каждого консенсусного объекта
|
||
- Cross-implementation conformance tests перед запуском mainnet
|
||
|
||
### Protocol layer
|
||
|
||
Собственная реализация поверх криптографического ядра:
|
||
|
||
| Компонент | Назначение |
|
||
|-----------|------------|
|
||
| Merkle-деревья | State Root, blocks_root, IC proofs (из SHA-256 вызовов) |
|
||
| VDF scheduling | Управление Beacon и Service цепочками |
|
||
| State machine | Account Table, Pending Transfers, state transitions |
|
||
| P2P gossip | Распространение блоков и чекпоинтов |
|
||
|
||
### Инфраструктура
|
||
|
||
| Библиотека | Назначение |
|
||
|------------|------------|
|
||
| RocksDB | Хранение Account Table и блоков |
|
||
| libp2p | P2P транспорт |
|
||
|
||
Production: Rust.
|
||
|
||
---
|
||
|
||
## Архитектура
|
||
|
||
```
|
||
┌─────────────────────────────────┐
|
||
│ Wallet │
|
||
│ Кошелёк, баланс, переводы │
|
||
│ FN-DSA-512 keypair │
|
||
└──────────────┬──────────────────┘
|
||
│
|
||
┌──────────────┴──────────────────┐
|
||
│ TimeChain │
|
||
│ │
|
||
│ Beacon ──→ Service ──→ Execution
|
||
│ (часы) (служба) (состояние)
|
||
│ │
|
||
│ Account Chain (Block Lattice) │
|
||
│ Account Table, IC, QC │
|
||
│ SHA-256, FN-DSA-512 │
|
||
└─────────────────────────────────┘
|
||
```
|