diff --git a/@l10n/ru/docs/consensus/hf16.md b/@l10n/ru/docs/consensus/hf16.md index 9697cf80b3..2c2053543b 100644 --- a/@l10n/ru/docs/consensus/hf16.md +++ b/@l10n/ru/docs/consensus/hf16.md @@ -6,6 +6,19 @@ HF16 назначен на **31 октября 2026, 00:00:00 UTC** (`1793404800 После сборки master перед распространением проверьте ревизию/версию конкретного образа, запуск, синхронизацию и производство блоков. Сохраните настроенный ключ валидатора и резервную копию данных. Удаление каталога данных не является процедурой обновления. +### Проверка готовности + +Для активации нужно `CHAIN_HARDFORK_REQUIRED_VALIDATORS` = 17 из 21 валидаторов расписания, производящих блоки с голосом за 4.2.0. Если к 31.10.2026 00:00 UTC обновилось меньше, форк активируется на блоке, где появится 17-й голос, без объявленного момента. До даты проверьте оба сигнала: + +```json +{ "method": "database_api.get_next_scheduled_hardfork", "params": [] } +{ "method": "validator_api.get_validators_by_vote", "params": ["", 21] } +``` + +- `get_next_scheduled_hardfork` возвращает `hf_version` 4.2.0 и `live_time` 2026-10-31T00:00:00, когда голосование набрало порог. До этого поле повторяет текущую версию. +- В `get_validators_by_vote` посчитайте записи с `hardfork_version_vote` 4.2.0 и `hardfork_time_vote` 2026-10-31T00:00:00. `running_version` показывает бинарник, с которым валидатор последний раз произвёл блок. Цель: не меньше 17 из 21 активных. +- Подсчёт идёт по валидаторам *расписания* (один на слот) и пропускает аварийного валидатора `committee`. `get_validators_by_vote ["", 21]` совпадает с этим набором, только пока расписание — это топ-21 по голосам; чтобы посчитать ровно то, что видит подсчёт, возьмите имена из `validator_api.get_active_validators`, уберите `committee` и проверьте каждого через `validator_api.get_validator_by_account`. + ## Слоты, QC, TC и финальность - При HF16 рабочий слот меняется с **3 секунд на 1 секунду**. Читайте текущее значение `get_config` и время блоков: прежняя константа `CHAIN_BLOCK_INTERVAL` не задаёт слот после форка. diff --git a/docs/consensus/hf16.md b/docs/consensus/hf16.md index da03e5e81d..e2405ab142 100644 --- a/docs/consensus/hf16.md +++ b/docs/consensus/hf16.md @@ -6,6 +6,19 @@ HF16 is scheduled for **2026-10-31 00:00:00 UTC** (`1793404800`), version **4.2. After the master image is built, check its revision/version, startup, synchronization and block production before distributing that exact image/digest. Keep the configured validator key and data-directory backup. Do not delete the data directory as an update procedure. +### Verify readiness + +Activation needs `CHAIN_HARDFORK_REQUIRED_VALIDATORS` = 17 of the 21 scheduled validators producing blocks with the 4.2.0 vote. If fewer have upgraded by 2026-10-31 00:00 UTC, the fork activates at the block where the 17th vote lands, with no announced moment. Check both signals before the date: + +```json +{ "method": "database_api.get_next_scheduled_hardfork", "params": [] } +{ "method": "validator_api.get_validators_by_vote", "params": ["", 21] } +``` + +- `get_next_scheduled_hardfork` returns `hf_version` 4.2.0 and `live_time` 2026-10-31T00:00:00 once the vote has locked in. Until then it mirrors the current version. +- In `get_validators_by_vote`, count entries with `hardfork_version_vote` 4.2.0 and `hardfork_time_vote` 2026-10-31T00:00:00. `running_version` shows the binary each validator last produced with. Target: at least 17 of the active 21. +- The tally counts the *scheduled* validators (one per slot) and skips the emergency committee validator. `get_validators_by_vote ["", 21]` matches that set only while the schedule is the top 21 by vote; to count exactly what the tally sees, take the names from `validator_api.get_active_validators`, drop `committee`, and look each one up with `validator_api.get_validator_by_account`. + ## Slots, QC, TC and finality - The runtime slot changes from **3 seconds to 1 second** at HF16. Use the node's current `get_config` value and block timestamps; the compile-time legacy `CHAIN_BLOCK_INTERVAL` is not the post-fork slot. diff --git a/plugins/snapshot/plugin.cpp b/plugins/snapshot/plugin.cpp index 69098d693f..6bb5c1d7e3 100644 --- a/plugins/snapshot/plugin.cpp +++ b/plugins/snapshot/plugin.cpp @@ -229,6 +229,17 @@ inline uint32_t import_dynamic_global_properties( ? v["round_anchor_time"].as() : fc::time_point_sec(); obj.round_anchor_round = v.get_object().contains("round_anchor_round") ? v["round_anchor_round"].as() : 0; + // PM one-time seed flags. Export is reflection-based and carries them; + // without these lines a restored node re-seeds on its first block and its + // own later snapshots disagree with the network. Absent or null = not seeded. + obj.pm_frozen_counters_seeded = v.get_object().contains("pm_frozen_counters_seeded") + && !v["pm_frozen_counters_seeded"].is_null() && v["pm_frozen_counters_seeded"].as_bool(); + obj.pm_frozen_counters_reseeded_v1 = v.get_object().contains("pm_frozen_counters_reseeded_v1") + && !v["pm_frozen_counters_reseeded_v1"].is_null() && v["pm_frozen_counters_reseeded_v1"].as_bool(); + obj.pm_active_markets_seeded = v.get_object().contains("pm_active_markets_seeded") + && !v["pm_active_markets_seeded"].is_null() && v["pm_active_markets_seeded"].as_bool(); + obj.pm_oracle_gauges_seeded = v.get_object().contains("pm_oracle_gauges_seeded") + && !v["pm_oracle_gauges_seeded"].is_null() && v["pm_oracle_gauges_seeded"].as_bool(); }); return 1; }