Жизненный цикл Валидатора¶
Этапы жизни валидатора¶
1. Создание¶
Триггер: Транзакция STAKE с достаточной суммой
Условия:
tx.amount >= min_validator_stakepub_keyприсутствует в payload- Баланс отправителя достаточен
Что происходит:
# В State.apply_transaction
val_addr = address_from_pubkey(pub_key_bytes, prefix="cpcvalcons")
val = Validator(
address=val_addr,
pq_pub_key=pub_key_hex,
power=tx.amount,
is_active=False, # Еще не активен!
reward_address=tx.from_address
)
Статус: is_active = False
2. Ожидание (Pending)¶
Период: До следующей эпохи
Что происходит:
- Валидатор создан, но не участвует в консенсусе
- Не может производить блоки
- Не получает награды
Проверка:
Вывод:
{
"epoch": 1,
"validators": [
{
"address": "cpcvalcons1...",
"power": "1500000000000000000000",
"is_active": false, // ← Еще не активен
"reward_address": "cpc1..."
}
]
}
3. Активация¶
Триггер: Переход эпохи (каждые N блоков)
Процесс:
-
Собрать всех валидаторов:
-
Отфильтровать по минимальному стейку:
-
Сортировать по стейку (по убыванию):
-
Выбрать топ-N:
-
Активировать:
-
Деактивировать остальных:
Статус: is_active = True
4. Активная валидация¶
Период: Пока валидатор в топ-N
Что происходит:
- Участвует в консенсусе (Round-Robin)
- Может производить блоки в свой слот
- Получает награды за блоки и комиссии
Round-Robin:
def get_proposer(height: int) -> Validator:
active_validators = [v for v in validators if v.is_active]
index = height % len(active_validators)
return active_validators[index]
Пример:
Блок 10: Валидатор A (index 0)
Блок 11: Валидатор B (index 1)
Блок 12: Валидатор C (index 2)
Блок 13: Валидатор A (index 0) # Цикл повторяется
5. Деактивация¶
Причины:
- Недостаточный стейк:
- Валидатор упал ниже
min_validator_stake -
Или другие валидаторы обогнали по стейку
-
Вытеснение из топ-N:
- Появились валидаторы с большим стейком
- Валидатор выпал из топ-N
Что происходит:
Последствия:
- Перестает производить блоки
- Не получает награды
- Может быть реактивирован в следующей эпохе (если вернется в топ-N)
6. Ре-стейкинг (Добавление стейка)¶
Триггер: Новая транзакция STAKE с тем же pub_key
Что происходит:
Результат:
- Повышение позиции в рейтинге
- Больше шансов остаться в топ-N
- Больше наград (если активен)
Эпоха¶
Определение¶
Эпоха — период между пересчетами набора валидаторов.
Длительность:
| Сеть | Блоки | Время (примерно) |
|---|---|---|
| Devnet | 10 | ~100 сек |
| Testnet | 100 | ~50 мин |
| Mainnet | 72 | ~72 мин |
Переход эпохи¶
Триггер:
Что происходит:
- Пересчет набора валидаторов
- Активация/деактивация
- Обновление
ConsensusEngine.validator_set
Примеры сценариев¶
Сценарий 1: Становление валидатором¶
Блок 0: Alice отправляет STAKE(1500 CPC)
Блок 1: Транзакция включена, валидатор создан (is_active=False)
Блок 2-9: Ожидание эпохи
Блок 10: Эпоха! Alice активируется (is_active=True)
Блок 11: Alice производит первый блок (Round-Robin)
Сценарий 2: Вытеснение из Топ-N¶
Эпоха 1: Топ-5: [A:2000, B:1800, C:1500, D:1200, E:1000]
Alice (1500) — активна
Эпоха 2: Топ-5: [A:2000, B:1800, C:1500, F:1400, D:1200]
Alice (1500) — все еще активна
Эпоха 3: Топ-5: [A:2000, B:1800, G:1600, C:1500, F:1400]
Alice (1500) — деактивирована (вытеснена G)
Сценарий 3: Возвращение в Топ-N¶
Эпоха 1: Alice деактивирована (6-я по стейку)
Эпоха 1: Alice отправляет STAKE(+500 CPC)
Эпоха 2: Alice возвращается в топ-5, активируется
Мониторинг¶
Проверка статуса валидатора¶
Вывод:
{
"epoch": 2,
"validators": [
{
"address": "cpcvalcons1alice...",
"pq_pub_key": "02a1b2c3...",
"power": "1500000000000000000000",
"is_active": true,
"reward_address": "cpc1alice..."
},
{
"address": "cpcvalcons1bob...",
"pq_pub_key": "02b2c3d4...",
"power": "1200000000000000000000",
"is_active": true,
"reward_address": "cpc1bob..."
}
]
}
Проверка текущего Proposer¶
Вывод:
Расчет Proposer:
height = 15
epoch = height // 10 # = 1
active_validators = get_active_validators()
proposer_index = height % len(active_validators)
proposer = active_validators[proposer_index]
Следующие шаги¶
- Основы стейкинга — Основы стейкинга
- Награды — Награды за валидацию
- Настройка ноды — Запуск ноды валидатора