diff --git a/.gitignore b/.gitignore index 65e7075bf2..3101341f91 100644 --- a/.gitignore +++ b/.gitignore @@ -38,7 +38,7 @@ tests/intense_test tests/performance_test wallet.json -witness_node_data_dir +node_data_dir *.wallet diff --git a/.qoder/docs/block-processing.md b/.qoder/docs/block-processing.md index a5a3161333..82ed5e64c0 100644 --- a/.qoder/docs/block-processing.md +++ b/.qoder/docs/block-processing.md @@ -393,7 +393,7 @@ When block at T=6 is pushed, `update_global_dynamic_data()` counts `missed_block |---|---|---| | Sync status | Chain is not stale (or `enable-stale-production`) | `not_synced` | | Slot time | `get_slot_at_time(now) > 0` | `not_time_yet` | -| validator ownership | Scheduled validator is in our `_witnesses` set | `not_my_turn` | +| validator ownership | Scheduled validator is in our `_validators` set | `not_my_turn` | | Signing key | validator has non-zero `signing_key` on chain | `not_my_turn` | | Private key | We have the private key for the signing key | `no_private_key` | | Participation | Network participation ≥ required (pre-HF12 only) | `low_participation` | diff --git a/.qoder/docs/consensus-emergency-params.md b/.qoder/docs/consensus-emergency-params.md index 19c4c94aa4..6f0a2bf334 100644 --- a/.qoder/docs/consensus-emergency-params.md +++ b/.qoder/docs/consensus-emergency-params.md @@ -428,7 +428,7 @@ maybe_produce_block() │ ├─ [HF12+] Is emergency_consensus_active? │ └─ Yes: Three-state safety handles production/sync checks: - │ ├─ IS emergency master? (emergency key in _witnesses) + │ ├─ IS emergency master? (emergency key in _validators) │ │ └─ Yes: _production_enabled = true (bypass sync/stale/participation) │ └─ NOT emergency master (slave): │ ├─ _production_enabled already? → continue diff --git a/.qoder/docs/hf13-validator-reward-sharing.md b/.qoder/docs/hf13-validator-reward-sharing.md index b78eaec4b8..bacacc166a 100644 --- a/.qoder/docs/hf13-validator-reward-sharing.md +++ b/.qoder/docs/hf13-validator-reward-sharing.md @@ -113,14 +113,14 @@ wit.pending_stakeholder_reward = 0 ### Important notes -- **Vote weight** used: `stakeholder.witness_vote_fair_weight()` — total stake (own vesting +- **Vote weight** used: `stakeholder.validator_vote_fair_weight()` — total stake (own vesting shares + shares proxied by accounts that delegated voting to this stakeholder) divided by - `witnesses_voted_for`. This matches the per-validator weight used in consensus scheduling: + `validators_voted_for`. This matches the per-validator weight used in consensus scheduling: a stakeholder who splits their vote across N validators contributes 1/N of their stake to each validator's distribution pool. - **Time-weighted distribution**: each stakeholder's weight is multiplied by the number of blocks they were actually voting for this validator within the current epoch (see `vote_created_block` - on `witness_vote_object`). A stakeholder who joined mid-epoch receives a proportionally smaller + on `validator_vote_object`). A stakeholder who joined mid-epoch receives a proportionally smaller share. - **Pre-HF13 votes** (`vote_created_block == 0`) are treated as having voted since epoch start (`first_block = epoch_start_block`), so they receive a full-epoch weight. No penalty for @@ -129,7 +129,7 @@ wit.pending_stakeholder_reward = 0 Stakeholders with a computed share below this threshold receive nothing; their portion is returned to the validator as dust (see design rationale below). - **No-stakeholder case**: if a validator has no stakeholders, the entire accumulated pool is - returned to the validator via `witness_reward_operation`. + returned to the validator via `validator_reward_operation`. #### Dust design rationale @@ -141,7 +141,7 @@ lies with the stakeholder, not with the validator. Consequently, unclaimed dust is **not burned**. After all eligible stakeholders are paid, any remainder (dust from integer rounding, plus skipped sub-threshold shares) is transferred back to -the validator via `witness_reward_operation`. The validator retains what their stakeholders +the validator via `validator_reward_operation`. The validator retains what their stakeholders collectively failed to claim — no TOKEN leaves the system, and the validator is not penalised for stakeholders with negligible weight. @@ -163,7 +163,7 @@ pending_stakeholder_reward = The pool that stakeholders receive at epoch end is thus a weighted mix of both rates. This is the intended behaviour: the validator controls their own split on a per-block basis, and stakeholders -observe the change immediately on-chain via the `sharing_rate` field of the `witness_object`. +observe the change immediately on-chain via the `sharing_rate` field of the `validator_object`. --- @@ -174,7 +174,7 @@ the **time-weighted distribution** described above. ### How it works -`witness_vote_object` stores `vote_created_block` — the block number when the vote was cast. At +`validator_vote_object` stores `vote_created_block` — the block number when the vote was cast. At epoch end, each stakeholder's effective weight is scaled by: ``` @@ -191,7 +191,7 @@ The protection covers **new votes** only. If a stakeholder already held a vote epoch, they receive a full-epoch weight regardless of their stake changes within the epoch. This is acceptable: they were genuine stakeholders. -Vote removal before epoch end results in the stakeholder not appearing in `witness_vote_index` at +Vote removal before epoch end results in the stakeholder not appearing in `validator_vote_index` at distribution time, so they receive nothing — no exploit in this direction. --- @@ -323,15 +323,14 @@ If auto-recovery is not configured, or the recovery path fails, perform the foll systemctl stop vizd # 2. Delete shared memory (forces clean open on next start) -rm -f /path/to/witness_node_data_dir/shared_memory.bin -rm -f /path/to/witness_node_data_dir/shared_memory.meta +rm -f /path/to/node_data_dir/shared_memory.bin # Option A — restore from snapshot + replay dlt_block_log: ./vizd --replay-from-snapshot /path/to/snapshot-block-XXXXXXXX.json \ - --data-dir /path/to/witness_node_data_dir + --data-dir /path/to/node_data_dir # Option B — full replay from block_log (slow): -./vizd --replay --data-dir /path/to/witness_node_data_dir +./vizd --replay --data-dir /path/to/node_data_dir ``` After Option A the node replays `dlt_block_log` automatically (same path as auto-recovery), diff --git a/.qoder/docs/plugins.md b/.qoder/docs/plugins.md index 0f4aea80d3..9ec2a3d2a1 100644 --- a/.qoder/docs/plugins.md +++ b/.qoder/docs/plugins.md @@ -145,7 +145,7 @@ Peer-to-peer networking for block and transaction propagation. **Config options:** ```ini p2p-endpoint = 0.0.0.0:2001 -p2p-seed-node = seed.viz.world:2001 +p2p-seed-node = seed1.viz.world:2001 p2p-max-connections = 200 p2p-stats-enabled = true p2p-stats-interval = 300 diff --git a/.qoder/docs/snapshot-plugin.md b/.qoder/docs/snapshot-plugin.md index abed79ee50..b9075419dc 100644 --- a/.qoder/docs/snapshot-plugin.md +++ b/.qoder/docs/snapshot-plugin.md @@ -626,6 +626,7 @@ With `config.ini`: ```ini trusted-snapshot-peer = seed1.viz.world:8092 trusted-snapshot-peer = seed2.viz.world:8092 +trusted-snapshot-peer = seed3.viz.world:8092 ``` Since `sync-snapshot-from-trusted-peer` defaults to `false`, you must explicitly enable it in `config.ini` along with `trusted-snapshot-peer`: @@ -633,6 +634,7 @@ Since `sync-snapshot-from-trusted-peer` defaults to `false`, you must explicitly ```ini trusted-snapshot-peer = seed1.viz.world:8092 trusted-snapshot-peer = seed2.viz.world:8092 +trusted-snapshot-peer = seed3.viz.world:8092 sync-snapshot-from-trusted-peer = true ``` diff --git a/@l10n/ru/docs/advanced/database-schema.md b/@l10n/ru/docs/advanced/database-schema.md index e3fd80fa25..9f89d4668b 100644 --- a/@l10n/ru/docs/advanced/database-schema.md +++ b/@l10n/ru/docs/advanced/database-schema.md @@ -48,7 +48,7 @@ VIZ Ledger использует ChainBase — персистентное хра Аккаунты хранят балансы, состояние вестинга, метрики делегирования, пропускную способность, флаги аукциона/продажи и участие в управлении. -**Ключевые поля:** `name`, `balance` (VIZ), `vesting_shares`, `delegated_vesting_shares`, `received_vesting_shares`, `energy`, `next_vesting_withdrawal`, `witnesses_voted_for`, `recovery_account`. +**Ключевые поля:** `name`, `balance` (VIZ), `vesting_shares`, `delegated_vesting_shares`, `received_vesting_shares`, `energy`, `next_vesting_withdrawal`, `validators_voted_for`, `recovery_account`. **Индексы:** @@ -94,9 +94,9 @@ VIZ Ledger использует ChainBase — персистентное хра --- -## Объекты валидатора (Witness) +## Объекты валидатора -**Индексы `witness_object`:** +**Индексы `validator_object`:** | Тег | Ключ | |-----|------| diff --git a/@l10n/ru/docs/advanced/dlt-architecture.md b/@l10n/ru/docs/advanced/dlt-architecture.md index 0bf6c03673..291c6dcf92 100644 --- a/@l10n/ru/docs/advanced/dlt-architecture.md +++ b/@l10n/ru/docs/advanced/dlt-architecture.md @@ -124,7 +124,7 @@ CONNECTING → HANDSHAKING → SYNCING → ACTIVE → DISCONNECTED → BANNED Подсистема разрешения форков отслеживает конкурирующие верхушки цепочки: -- **Порог:** 42 блока расхождения запускают `resolve_fork()` (= `CHAIN_MAX_WITNESSES × 2`, один полный оборот расписания). +- **Порог:** 42 блока расхождения запускают `resolve_fork()` (= `CHAIN_MAX_VALIDATORS × 2`, один полный оборот расписания). - **Выбор:** Наиболее тяжёлая ветка по весу голосов. - **Гистерезис:** 6 последовательных блоков как победитель перед переключением (`CONFIRMATION_BLOCKS`). - **Статус:** `_fork_status` открыт через `is_on_majority_fork()` для плагина валидатора для проверки перед производством блоков. diff --git a/@l10n/ru/docs/advanced/hardfork-management.md b/@l10n/ru/docs/advanced/hardfork-management.md index 65ffb42999..c9298c8edf 100644 --- a/@l10n/ru/docs/advanced/hardfork-management.md +++ b/@l10n/ru/docs/advanced/hardfork-management.md @@ -57,7 +57,7 @@ HF12 вводит автоматическое восстановление се ### Активация -Если метка времени последнего необратимого блока (LIB) отстаёт от системных часов более чем на `CHAIN_EMERGENCY_CONSENSUS_TIMEOUT_SEC` (1 час), аварийный режим активируется автоматически. Создаётся аварийный аккаунт валидатора (`CHAIN_EMERGENCY_WITNESS_ACCOUNT = "committee"`) с известным публичным ключом (`CHAIN_EMERGENCY_WITNESS_PUBLIC_KEY`) и вставляется в расписание производства блоков. +Если метка времени последнего необратимого блока (LIB) отстаёт от системных часов более чем на `CHAIN_EMERGENCY_CONSENSUS_TIMEOUT_SEC` (1 час), аварийный режим активируется автоматически. Создаётся аварийный аккаунт валидатора (`CHAIN_EMERGENCY_VALIDATOR_ACCOUNT = "committee"`) с известным публичным ключом (`CHAIN_EMERGENCY_VALIDATOR_PUBLIC_KEY`) и вставляется в расписание производства блоков. ### Трёхуровневое обеспечение безопасности diff --git a/@l10n/ru/docs/api/json-rpc.md b/@l10n/ru/docs/api/json-rpc.md index 3335c76be7..39b4eeda22 100644 --- a/@l10n/ru/docs/api/json-rpc.md +++ b/@l10n/ru/docs/api/json-rpc.md @@ -52,7 +52,7 @@ |-----------------|-------|---------| | `database_api` | Активен | Запросы блоков, аккаунтов, состояния цепочки | | `network_broadcast_api` | Активен | Трансляция транзакций и блоков | -| `witness_api` | Активен | Запросы валидаторов | +| `validator_api` | Активен | Запросы валидаторов | | `account_by_key` | Активен | Обратный поиск по ключу | | `account_history` | Активен | История операций аккаунта | | `operation_history` | Активен | Запросы операций блока | @@ -119,18 +119,18 @@ --- -## Методы `witness_api` +## Методы `validator_api` | Метод | Описание | |-------|---------| -| `get_active_witnesses()` | Текущий активный набор валидаторов (21 аккаунт) | -| `get_witness_schedule()` | Полный объект расписания валидаторов | -| `get_witnesses(ids[])` | Валидаторы по внутренним ID | -| `get_witness_by_account(account)` | Объект валидатора для аккаунта | -| `get_witnesses_by_vote(lower_bound, limit)` | Валидаторы по убыванию веса голосов | -| `get_witnesses_by_counted_vote(lower_bound, limit)` | Валидаторы по числу голосов | -| `get_witness_count()` | Общее количество зарегистрированных валидаторов | -| `lookup_witness_accounts(lower_bound, limit)` | Список имён аккаунтов валидаторов | +| `get_active_validators()` | Текущий активный набор валидаторов (21 аккаунт) | +| `get_validator_schedule()` | Полный объект расписания валидаторов | +| `get_validators(ids[])` | Валидаторы по внутренним ID | +| `get_validator_by_account(account)` | Объект валидатора для аккаунта | +| `get_validators_by_vote(lower_bound, limit)` | Валидаторы по убыванию веса голосов | +| `get_validators_by_counted_vote(lower_bound, limit)` | Валидаторы по числу голосов | +| `get_validator_count()` | Общее количество зарегистрированных валидаторов | +| `lookup_validator_accounts(lower_bound, limit)` | Список имён аккаунтов валидаторов | --- @@ -214,7 +214,7 @@ plugin = database_api network_broadcast_api **Полный API-узел (добавить):** ```ini -plugin = witness_api account_by_key account_history operation_history +plugin = validator_api account_by_key account_history operation_history plugin = committee_api invite_api paid_subscription_api ``` diff --git a/@l10n/ru/docs/consensus/block-processing.md b/@l10n/ru/docs/consensus/block-processing.md index a925b19cf4..570af1c07f 100644 --- a/@l10n/ru/docs/consensus/block-processing.md +++ b/@l10n/ru/docs/consensus/block-processing.md @@ -279,7 +279,7 @@ check_block_post_validation_chain(): struct block_post_validation_message { block_id_type block_id; std::string witness_account; // имя валидатора - signature_type witness_signature; // sign(chain_id + block_id) + signature_type validator_signature; // sign(chain_id + block_id) }; ``` diff --git a/@l10n/ru/docs/consensus/emergency-consensus.md b/@l10n/ru/docs/consensus/emergency-consensus.md index 7d824e890a..5fdf5ffbf9 100644 --- a/@l10n/ru/docs/consensus/emergency-consensus.md +++ b/@l10n/ru/docs/consensus/emergency-consensus.md @@ -9,11 +9,11 @@ | Константа | Значение | Значение | |-----------|---------|---------| | `CHAIN_EMERGENCY_CONSENSUS_TIMEOUT_SEC` | 3600 с | Время простоя до активации | -| `CHAIN_EMERGENCY_WITNESS_ACCOUNT` | `"committee"` | Аккаунт экстренного производителя блоков | -| `CHAIN_EMERGENCY_WITNESS_PUBLIC_KEY` | `VIZ75CR...` | Детерминированный ключ подписи для экстренного режима | +| `CHAIN_EMERGENCY_VALIDATOR_ACCOUNT` | `"committee"` | Аккаунт экстренного производителя блоков | +| `CHAIN_EMERGENCY_VALIDATOR_PUBLIC_KEY` | `VIZ75CR...` | Детерминированный ключ подписи для экстренного режима | | `CHAIN_EMERGENCY_EXIT_NORMAL_BLOCKS` | 21 | Последовательные блоки реальных валидаторов для выхода | | `CHAIN_IRREVERSIBLE_THRESHOLD` | 75% | Доля слотов расписания для выхода | -| `CHAIN_MAX_WITNESSES` | 21 | Максимальное количество слотов валидаторов | +| `CHAIN_MAX_VALIDATORS` | 21 | Максимальное количество слотов валидаторов | ### Поля состояния в `dynamic_global_property_object` @@ -41,12 +41,12 @@ 1. Установить `dgp.emergency_consensus_active = true` и `dgp.emergency_consensus_start_block = block_num`. 2. Создать или обновить объект валидатора "committee": - - `signing_key = CHAIN_EMERGENCY_WITNESS_PUBLIC_KEY` + - `signing_key = CHAIN_EMERGENCY_VALIDATOR_PUBLIC_KEY` - `props = current_median_props` - Голоса за харфорки установлены на текущую применённую версию (нейтральный голосователь). 3. Отключить ВСЕХ реальных валидаторов: установить `signing_key = zero`, сбросить `penalty_percent = 0`, `current_run = 0`. 4. Удалить все объекты `witness_penalty_expire`. -5. Переопределить расписание валидаторов: все `CHAIN_MAX_WITNESSES` слотов → "committee". +5. Переопределить расписание валидаторов: все `CHAIN_MAX_VALIDATORS` слотов → "committee". 6. Уведомить fork DB: `_fork_db.set_emergency_mode(true)` (включает детерминированное разрешение хэш-ничьих). 7. Лог: `"EMERGENCY CONSENSUS MODE activated at block #N. No blocks for X seconds since LIB Y."` @@ -60,7 +60,7 @@ ```ini # Только для экстренного мастер-узла -emergency-private-key = 5Jzzz... # приватный ключ CHAIN_EMERGENCY_WITNESS_ACCOUNT +emergency-private-key = 5Jzzz... # приватный ключ CHAIN_EMERGENCY_VALIDATOR_ACCOUNT ``` | Роль | Проверка DLT-синхронизации | Проверка minority fork | Производство | @@ -105,7 +105,7 @@ Committee исключается из подсчёта версий харфор Каждое перестроение расписания проверяет условие выхода: ``` -real_witness_slots >= CHAIN_MAX_WITNESSES × 75% +real_witness_slots >= CHAIN_MAX_VALIDATORS × 75% ``` При 21 валидаторе: `21 × 0.75 = 15.75 → 15` слотов реальных валидаторов требуется. @@ -133,7 +133,7 @@ real_witness_slots >= CHAIN_MAX_WITNESSES × 75% ## Интеграция с Validator Guard -Плагин `witness_guard` продолжает работу во время экстренного режима и фактически становится более критичным: +Плагин `validator_guard` продолжает работу во время экстренного режима и фактически становится более критичным: - Реальные валидаторы отключаются (ключ подписи обнуляется) при активации. - Защита валидатора автоматически транслирует `validator_update_operation` для восстановления ключа подписи каждого валидатора, как только на цепочке обнаруживается нулевой ключ. @@ -199,7 +199,7 @@ real_witness_slots >= CHAIN_MAX_WITNESSES × 75% | 9 | `stale_sync_check_task` | Пропустить если голова мастера продвигается; разрешить если последователь застрял | | 10 | `handle_block` | Почти догнавшие блоки обрабатываются как нормальные в DLT-экстренном режиме | | 11 | `database::open` | Исправление расписания при запуске | -| 12 | `witness_guard` | Не подавлять восстановление ключей в экстренном режиме | +| 12 | `validator_guard` | Не подавлять восстановление ключей в экстренном режиме | | 13 | `snapshot import` | Совместимая обработка полей | | 14 | `update_witness_schedule` | Исключать committee из подсчёта версий харфорков | | 15 | `update_median_witness_props` | Исключать committee из вычисления медианы | diff --git a/@l10n/ru/docs/consensus/fair-dpos.md b/@l10n/ru/docs/consensus/fair-dpos.md index b44c3af2e2..0e5b8384a5 100644 --- a/@l10n/ru/docs/consensus/fair-dpos.md +++ b/@l10n/ru/docs/consensus/fair-dpos.md @@ -116,8 +116,8 @@ irreversibility_threshold = ceil(num_scheduled_validators * 2 / 3) Если в течение `CHAIN_EMERGENCY_CONSENSUS_TIMEOUT_SEC` (по умолчанию 1 час) не было произведено ни одного блока, цепочка переходит в **режим чрезвычайной ситуации**: -- Все 21 слот валидаторов назначаются `CHAIN_EMERGENCY_WITNESS_ACCOUNT` («committee»). -- Экстренный валидатор подписывает блоки с использованием `CHAIN_EMERGENCY_WITNESS_PUBLIC_KEY`. +- Все 21 слот валидаторов назначаются `CHAIN_EMERGENCY_VALIDATOR_ACCOUNT` («committee»). +- Экстренный валидатор подписывает блоки с использованием `CHAIN_EMERGENCY_VALIDATOR_PUBLIC_KEY`. - Все штрафы валидаторов сбрасываются; отключённые валидаторы повторно включаются. - Продвижение LIB приостанавливается в период чрезвычайной ситуации. - Режим чрезвычайной ситуации завершается после того, как `CHAIN_EMERGENCY_EXIT_NORMAL_BLOCKS` (21) последовательных обычных блоков продвигают LIB выше начального блока чрезвычайной ситуации. @@ -146,7 +146,7 @@ irreversibility_threshold = ceil(num_scheduled_validators * 2 / 3) | `required-participation` | `33` (33%) | Минимальное участие для производства блоков | | `enable-stale-production` | `false` | Обход проверки участия (только для тестовой сети) | | `emergency-private-key` | — | Опциональный ключ подписи для экстренного консенсуса | -| Активные валидаторы | 21 | Задано в `CHAIN_MAX_WITNESSES` | +| Активные валидаторы | 21 | Задано в `CHAIN_MAX_VALIDATORS` | | Интервал блока | 3 с | `CHAIN_BLOCK_INTERVAL` | | Порог LIB | ⌈21 × 2/3⌉ = 14 | Блоки, подтверждающие необратимость | | Таймаут чрезвычайной ситуации | 3600 с | `CHAIN_EMERGENCY_CONSENSUS_TIMEOUT_SEC` | diff --git a/@l10n/ru/docs/consensus/hardforks.md b/@l10n/ru/docs/consensus/hardforks.md index b1a1ca4271..46d2c83c4b 100644 --- a/@l10n/ru/docs/consensus/hardforks.md +++ b/@l10n/ru/docs/consensus/hardforks.md @@ -44,7 +44,7 @@ HF13 (версия 3.2.0) ввёл: **Совместное использование наград валидаторов**: часть награды валидатора каждого блока перераспределяется пропорционально аккаунтам, проголосовавшим за этого валидатора (по их весу голосов в SHARES). -- Новое поле в `witness_object`: `reward_percent` — доля награды за блок, делимая с голосующими (0–10000 базисных пунктов). +- Новое поле в `validator_object`: `reward_percent` — доля награды за блок, делимая с голосующими (0–10000 базисных пунктов). - Новая виртуальная операция: `validator_reward_virtual_operation` — срабатывает один раз при каждом распределении наград. - Устанавливается через `validator_update_operation`. @@ -121,7 +121,7 @@ case CHAIN_HARDFORK_N: { | Плагин | Что обновить | |--------|-------------| | `account_history` | Добавить экстрактор воздействия для любой новой виртуальной операции | -| `witness_api` | Добавить новые поля из `witness_object` в `witness_api_object` | +| `validator_api` | Добавить новые поля из `validator_object` в `validator_api_object` | | `snapshot` | Добавить новые объекты chainbase в `serialize_state` / `load_snapshot` | --- @@ -163,7 +163,7 @@ case CHAIN_HARDFORK_N: { - [ ] Все новые поля имеют нулевые значения по умолчанию; комментарий в `apply_hardfork` объясняет, почему миграция не нужна - [ ] Новый evaluator зарегистрирован в `initialize_evaluators()` - [ ] Новая виртуальная операция зарегистрирована в плагине `account_history` -- [ ] `witness_api_object` обновлён если изменился `witness_object` +- [ ] `validator_api_object` обновлён если изменился `validator_object` - [ ] Плагин snapshot обновлён если добавлены новые объекты chainbase --- diff --git a/@l10n/ru/docs/development/building.md b/@l10n/ru/docs/development/building.md index 491b11a837..7ba29470f0 100644 --- a/@l10n/ru/docs/development/building.md +++ b/@l10n/ru/docs/development/building.md @@ -113,9 +113,7 @@ build-msvc.bat | Dockerfile | Описание | |-----------|---------| -| `Dockerfile-production` | Полный узел, Release, без MongoDB | -| `Dockerfile-lowmem` | То же, но с `LOW_MEMORY_NODE=ON` | -| `Dockerfile-mongo` | Включён плагин MongoDB | +| `Dockerfile-production` | Полный узел мейннета (Release) | | `Dockerfile-testnet` | Testnet (`BUILD_TESTNET=ON`) | Все Dockerfile используют двухэтапную сборку для минимизации размера образа и пакеты Boost 1.71 (`libboost-coroutine-dev`, `libboost-context-dev`). @@ -129,7 +127,6 @@ build-msvc.bat | `BUILD_TESTNET` | OFF | Сборка для testnet | | `LOW_MEMORY_NODE` | OFF | Исключить неконсенсусные данные (уменьшает RAM) | | `CHAINBASE_CHECK_LOCKING` | OFF | Включить проверку блокировок (только для разработки) | -| `ENABLE_MONGO_PLUGIN` | OFF | Включить плагин MongoDB | | `BUILD_SHARED_LIBRARIES` | OFF | Собирать разделяемые библиотеки | | `USE_PCH` | OFF | Включить предкомпилированные заголовки (ускоряет пересборку) | diff --git a/@l10n/ru/docs/development/testing.md b/@l10n/ru/docs/development/testing.md index f05c628a67..25029f95fd 100644 --- a/@l10n/ru/docs/development/testing.md +++ b/@l10n/ru/docs/development/testing.md @@ -128,8 +128,6 @@ CI-матрица собирает Docker-образы для нескольки | Вариант | Dockerfile | |---------|-----------| | Стандартный | `Dockerfile-production` | -| Low-memory | `Dockerfile-lowmem` | -| MongoDB | `Dockerfile-mongo` | | Testnet | `Dockerfile-testnet` | Сборки запускаются для каждой ветки и тега, с публикацией артефактов при наличии учётных данных. diff --git a/@l10n/ru/docs/governance/chain-properties.md b/@l10n/ru/docs/governance/chain-properties.md index 2e59ed2281..0358a42f28 100644 --- a/@l10n/ru/docs/governance/chain-properties.md +++ b/@l10n/ru/docs/governance/chain-properties.md @@ -41,7 +41,7 @@ ### 3. Применение -Результирующий объект `median_props` сохраняется в `witness_schedule_object` и применяется при обработке всех блоков. +Результирующий объект `median_props` сохраняется в `validator_schedule_object` и применяется при обработке всех блоков. --- @@ -69,11 +69,11 @@ | Параметр | Тип | По умолчанию | Описание | |---------|-----|------------|---------| -| `inflation_witness_percent` | uint16 (bp) | 2000 (20%) | Доля валидаторов от блочной инфляции | +| `inflation_validator_percent` | uint16 (bp) | 2000 (20%) | Доля валидаторов от блочной инфляции | | `inflation_ratio_committee_vs_reward_fund` | uint16 (bp) | 5000 (50%) | Разделение оставшейся инфляции: фонд комитета vs фонд вознаграждений | | `inflation_recalc_period` | uint32 (блоки) | 806400 (~28д) | Как часто пересчитывается инфляция | -Поток инфляции: `block_reward × inflation_witness_percent` → валидатор. Остаток делится: `inflation_ratio_committee_vs_reward_fund` → фонд комитета; остальное → фонд вознаграждений за награды. +Поток инфляции: `block_reward × inflation_validator_percent` → валидатор. Остаток делится: `inflation_ratio_committee_vs_reward_fund` → фонд комитета; остальное → фонд вознаграждений за награды. ### Система вознаграждений @@ -88,8 +88,8 @@ | Параметр | Тип | По умолчанию | Описание | |---------|-----|------------|---------| -| `witness_miss_penalty_percent` | uint16 (bp) | 100 (1%) | Снижение веса голосов при пропуске блока | -| `witness_miss_penalty_duration` | uint32 (с) | 86400 (1д) | Продолжительность штрафа за пропуск | +| `validator_miss_penalty_percent` | uint16 (bp) | 100 (1%) | Снижение веса голосов при пропуске блока | +| `validator_miss_penalty_duration` | uint32 (с) | 86400 (1д) | Продолжительность штрафа за пропуск | ### Комиссии @@ -101,7 +101,7 @@ | `create_paid_subscription_fee` | asset (VIZ) | 100.000 VIZ | Комиссия за создание платной подписки | | `account_on_sale_fee` | asset (VIZ) | 10.000 VIZ | Комиссия за выставление аккаунта на продажу | | `subaccount_on_sale_fee` | asset (VIZ) | 100.000 VIZ | Комиссия за выставление прав создания субаккаунта на продажу | -| `witness_declaration_fee` | asset (VIZ) | 10.000 VIZ | Единовременная комиссия за регистрацию валидатора | +| `validator_declaration_fee` | asset (VIZ) | 10.000 VIZ | Единовременная комиссия за регистрацию валидатора | | `create_invite_min_balance` | asset (VIZ) | 10.000 VIZ | Минимальный баланс инвайта | ### Вывод из вестинга @@ -119,9 +119,9 @@ | Версия | Индекс | Хардфорк | Добавленные поля | |--------|--------|---------|----------------| | `chain_properties_init` | 0 | Генезис | account_creation_fee, maximum_block_size, параметры делегирования, курация, пропускная способность, стоимость флага, минимальные rshares, порог комитета | -| `chain_properties_hf4` | 1 | HF4 | inflation_witness_percent, inflation_ratio_committee_vs_reward_fund, inflation_recalc_period | -| `chain_properties_hf6` | 2 | HF6 | data_operations_cost_additional_bandwidth, witness_miss_penalty_percent, witness_miss_penalty_duration | -| `chain_properties_hf9` | 3 | HF9 | create_invite_min_balance, committee_create_request_fee, create_paid_subscription_fee, account_on_sale_fee, subaccount_on_sale_fee, witness_declaration_fee, withdraw_intervals | +| `chain_properties_hf4` | 1 | HF4 | inflation_validator_percent, inflation_ratio_committee_vs_reward_fund, inflation_recalc_period | +| `chain_properties_hf6` | 2 | HF6 | data_operations_cost_additional_bandwidth, validator_miss_penalty_percent, validator_miss_penalty_duration | +| `chain_properties_hf9` | 3 | HF9 | create_invite_min_balance, committee_create_request_fee, create_paid_subscription_fee, account_on_sale_fee, subaccount_on_sale_fee, validator_declaration_fee, withdraw_intervals | Для всех новых публикаций параметров валидатора используйте индекс версии 3 (`chain_properties_hf9`). diff --git a/@l10n/ru/docs/governance/staking-and-dao.md b/@l10n/ru/docs/governance/staking-and-dao.md index f61b0083fc..0da38f6615 100644 --- a/@l10n/ru/docs/governance/staking-and-dao.md +++ b/@l10n/ru/docs/governance/staking-and-dao.md @@ -75,10 +75,10 @@ SHARES — это универсальный токен управления. К Вес голоса **делится поровну** между всеми валидаторами, за которых голосует аккаунт: ``` -fair_weight = effective_vesting_shares / witnesses_voted_for +fair_weight = effective_vesting_shares / validators_voted_for ``` -Это предотвращает концентрацию — голосование за 10 валидаторов даёт каждому 1/10 вашего веса. Аккаунты также могут установить доверенного представителя (`account_witness_proxy_operation`), делегировав все голоса за валидаторов другому аккаунту. +Это предотвращает концентрацию — голосование за 10 валидаторов даёт каждому 1/10 вашего веса. Аккаунты также могут установить доверенного представителя (`account_validator_proxy_operation`), делегировав все голоса за валидаторов другому аккаунту. ### 2. Голосование в Committee DAO @@ -159,7 +159,7 @@ rshares = effective_vesting_shares × energy / 10000 | `CHAIN_MAX_WITHDRAW_ROUTES` | 10 | Максимум маршрутов вывода на аккаунт | | `CHAIN_ENERGY_REGENERATION_SECONDS` | 432000 (5д) | Полное восстановление энергии | | `CHAIN_100_PERCENT` | 10000 | Знаменатель в базисных пунктах | -| `CHAIN_MAX_ACCOUNT_WITNESS_VOTES` | 100 | Максимум валидаторов на аккаунт | +| `CHAIN_MAX_ACCOUNT_VALIDATOR_VOTES` | 100 | Максимум валидаторов на аккаунт | --- diff --git a/@l10n/ru/docs/introduction/architecture.md b/@l10n/ru/docs/introduction/architecture.md index 65385414b6..8bfdfa6235 100644 --- a/@l10n/ru/docs/introduction/architecture.md +++ b/@l10n/ru/docs/introduction/architecture.md @@ -57,7 +57,7 @@ VIZ Ledger реализован как модульный C++-демон (`vizd` | `account_by_key` | Поиск счетов по публичному ключу | | `follow` | Индекс отношений подписок/игнорирования | | `tags` | Индексирование контента по тегам | -| `witness_api` | Запросы расписания валидаторов и ключей подписи | +| `validator_api` | Запросы расписания валидаторов и ключей подписи | | `debug_node` | Тестовые утилиты: внедрение блоков, установка времени | --- diff --git a/@l10n/ru/docs/introduction/key-concepts.md b/@l10n/ru/docs/introduction/key-concepts.md index 46643387de..cb2e2073ee 100644 --- a/@l10n/ru/docs/introduction/key-concepts.md +++ b/@l10n/ru/docs/introduction/key-concepts.md @@ -76,7 +76,7 @@ В отличие от стандартного DPOS, VIZ Ledger штрафует бездействие: - У каждого валидатора есть **оценка участия** на основе недавнего производства блоков. - Если участие по всей сети опускается ниже `required-participation` (по умолчанию 33%), производство блоков приостанавливается. -- Валидаторы, пропускающие слишком много блоков, получают штраф к голосам, действующий в течение `witness_miss_penalty_duration` секунд. +- Валидаторы, пропускающие слишком много блоков, получают штраф к голосам, действующий в течение `validator_miss_penalty_duration` секунд. --- @@ -89,7 +89,7 @@ - `timestamp`: точное время слота - `witness`: имя производящего валидатора - `transactions[]`: список подписанных транзакций -- `witness_signature`: подпись валидатора +- `validator_signature`: подпись валидатора ### Транзакция @@ -112,7 +112,7 @@ | Получатель | Источник | |-----------|---------| -| Валидаторы | `inflation_witness_percent` от блочного вознаграждения | +| Валидаторы | `inflation_validator_percent` от блочного вознаграждения | | Комитет | Доля `inflation_ratio_committee_vs_reward_fund` | | Фонд вознаграждений | Остаток — распределяется через награды и голоса за контент | @@ -146,8 +146,8 @@ Ключевые параметры: - `account_creation_fee` — стоимость создания нового аккаунта - `maximum_block_size` — максимальный размер блока в байтах -- `inflation_witness_percent` — доля валидаторов от блочного вознаграждения -- `witness_miss_penalty_percent` / `witness_miss_penalty_duration` — штраф за пропуск блоков +- `inflation_validator_percent` — доля валидаторов от блочного вознаграждения +- `validator_miss_penalty_percent` / `validator_miss_penalty_duration` — штраф за пропуск блоков - `withdraw_intervals` — количество интервалов вывода из вестинга См. [Управление параметрами цепочки](../governance/chain-properties.md) для полного списка параметров. diff --git a/@l10n/ru/docs/node/building.md b/@l10n/ru/docs/node/building.md index 8ac23adeb0..60f278784d 100644 --- a/@l10n/ru/docs/node/building.md +++ b/@l10n/ru/docs/node/building.md @@ -126,7 +126,6 @@ build-msvc.bat | `BUILD_TESTNET` | `OFF` | Включить код для тестнета | | `LOW_MEMORY_NODE` | `OFF` | Исключить плагины истории/индексирования | | `CHAINBASE_CHECK_LOCKING` | `OFF` | Включить проверки блокировок (debug) | -| `ENABLE_MONGO_PLUGIN` | `OFF` | Собрать плагин MongoDB | | `BUILD_SHARED_LIBRARIES` | `OFF` | Собрать разделяемые библиотеки | | `USE_PCH` | `OFF` | Включить предкомпилированные заголовки (ускоряет пересборку) | @@ -165,8 +164,6 @@ python3 programs/build_helpers/configure_build.py --release | Файл | Назначение | |------|-----------| | `Dockerfile-production` | Полный узел мейннета (Release) | -| `Dockerfile-lowmem` | Низкопамятный узел (`LOW_MEMORY_NODE=ON`) | -| `Dockerfile-mongo` | Узел с плагином MongoDB | | `Dockerfile-testnet` | Узел тестнета (`BUILD_TESTNET=ON`) | Пример сборки: diff --git a/@l10n/ru/docs/node/configuration.md b/@l10n/ru/docs/node/configuration.md index 23cd6b0edd..d512af7195 100644 --- a/@l10n/ru/docs/node/configuration.md +++ b/@l10n/ru/docs/node/configuration.md @@ -7,8 +7,6 @@ | `config.ini` | Полный узел основной сети с публичным RPC | | `config_witness.ini` | Узел-валидатор (RPC на localhost, производство блоков) | | `config_testnet.ini` | Тестовая сеть / разработка | -| `config_mongo.ini` | Узел с бэкендом истории MongoDB | -| `config_lowmem.ini` | Маломощный консенсусный/сид-узел | | `config_stock_exchange.ini` | Потребитель рыночных данных (минимум плагинов) | | `config_debug.ini` | Режим отладки | @@ -26,6 +24,7 @@ p2p-max-connections = 200 # Начальные узлы для установки соединений (повторяемый параметр) p2p-seed-node = seed1.viz.world:2001 p2p-seed-node = seed2.viz.world:2001 +p2p-seed-node = seed3.viz.world:2001 # Контрольные точки: доверенные пары (block_num, block_id) (повторяемый параметр) # checkpoint = [12345,"0003039..." ] @@ -112,7 +111,7 @@ plugin = social_network tags follow account_history account_by_key plugin = committee_api invite_api paid_subscription_api custom_protocol_api # Только для узлов-валидаторов: -plugin = validator witness_api +plugin = validator validator_api ``` ### Наборы плагинов по типу узла @@ -120,7 +119,7 @@ plugin = validator witness_api | Тип узла | Плагины | |---------|--------| | Полный узел | Все перечисленные выше | -| Валидатор | `chain p2p webserver json_rpc database_api network_broadcast_api validator witness_api` | +| Валидатор | `chain p2p webserver json_rpc database_api network_broadcast_api validator validator_api` | | Маломощный сид | `chain p2p` | | Биржа | `chain p2p webserver json_rpc database_api network_broadcast_api account_history` | @@ -198,17 +197,6 @@ logger.p2p.appenders = p2p --- -## MongoDB (опционально) - -Применимо только при сборке с `ENABLE_MONGO_PLUGIN=ON`: - -```ini -plugin = mongo_db -mongodb-uri = mongodb://localhost:27017/vizd -``` - ---- - ## Полный справочник Все параметры по исходным файлам: diff --git a/@l10n/ru/docs/node/docker.md b/@l10n/ru/docs/node/docker.md index aeaa4b444c..a64bf41b97 100644 --- a/@l10n/ru/docs/node/docker.md +++ b/@l10n/ru/docs/node/docker.md @@ -9,8 +9,6 @@ VIZ Ledger поставляется с четырьмя Docker-образами | Dockerfile | Тег | Описание | |-----------|-----|----------| | `Dockerfile-production` | `latest` | Полный узел мейннета (Release, все плагины) | -| `Dockerfile-lowmem` | `lowmem` | Низкопамятный узел (`LOW_MEMORY_NODE=ON`, без индексов истории) | -| `Dockerfile-mongo` | `mongo` | Полный узел с плагином истории MongoDB | | `Dockerfile-testnet` | `testnet` | Узел тестнета (`BUILD_TESTNET=ON`) | --- @@ -62,7 +60,7 @@ docker run -d \ | Переменная | Описание | Пример | |------------|----------|--------| -| `VIZD_SEED_NODES` | Список сид-узлов через пробел (переопределяет `/etc/vizd/seednodes`) | `seed1.viz.world:2001 seed2.viz.world:2001` | +| `VIZD_SEED_NODES` | Список сид-узлов через пробел (переопределяет `/etc/vizd/seednodes`) | `seed1.viz.world:2001 seed2.viz.world:2001 seed3.viz.world:2001` | | `VIZD_RPC_ENDPOINT` | Переопределить HTTP RPC endpoint | `0.0.0.0:8090` | | `VIZD_P2P_ENDPOINT` | Переопределить P2P endpoint | `0.0.0.0:2001` | | `VIZD_WITNESS` | Имя аккаунта валидатора (включает производство блоков) | `alice` | @@ -123,21 +121,19 @@ docker build \ -t vizd:local \ . -# Low-memory +# Testnet docker build \ - -f share/vizd/docker/Dockerfile-lowmem \ - -t vizd:lowmem \ + -f share/vizd/docker/Dockerfile-testnet \ + -t vizd:testnet \ . ``` ### CMake-флаги для каждого образа -| Образ | `LOW_MEMORY_NODE` | `ENABLE_MONGO_PLUGIN` | `BUILD_TESTNET` | -|-------|:-----------------:|:---------------------:|:---------------:| -| production | OFF | OFF | OFF | -| lowmem | ON | OFF | OFF | -| mongo | OFF | ON | OFF | -| testnet | OFF | OFF | ON | +| Образ | `LOW_MEMORY_NODE` | `BUILD_TESTNET` | +|-------|:-----------------:|:---------------:| +| production | OFF | OFF | +| testnet | OFF | ON | --- @@ -161,7 +157,7 @@ docker build \ | Тип узла | RAM | Диск | |----------|-----|------| | Полный узел (мейннет) | 8 ГБ+ | 50 ГБ+ | -| Низкопамятный / валидатор | 4 ГБ | 20 ГБ | +| Узел-валидатор | 4 ГБ | 20 ГБ | | Тестнет | 4 ГБ | 10 ГБ | Начинайте с размера разделяемой памяти, удобно помещающегося в RAM. В `config.ini`: diff --git a/@l10n/ru/docs/node/getting-started.md b/@l10n/ru/docs/node/getting-started.md index cef6a93e79..538b83ee05 100644 --- a/@l10n/ru/docs/node/getting-started.md +++ b/@l10n/ru/docs/node/getting-started.md @@ -122,6 +122,7 @@ cp share/vizd/config/config.ini /data/vizd/config.ini p2p-endpoint = 0.0.0.0:2001 p2p-seed-node = seed1.viz.world:2001 p2p-seed-node = seed2.viz.world:2001 +p2p-seed-node = seed3.viz.world:2001 # RPC webserver-http-endpoint = 0.0.0.0:8090 @@ -172,7 +173,6 @@ curl -s -X POST http://localhost:8090 \ | Валидатор | `config_witness.ini` | Производство блоков, RPC только на localhost | | Тестовая сеть | `config_testnet.ini` | Разработка и тестирование | | Малая память | `config.ini` + флаг сборки `LOW_MEMORY_NODE` | Только консенсус, без индексов истории | -| MongoDB | `config_mongo.ini` | Полная история в MongoDB | --- diff --git a/@l10n/ru/docs/node/snapshot.md b/@l10n/ru/docs/node/snapshot.md index 9709606a12..c7ea34da35 100644 --- a/@l10n/ru/docs/node/snapshot.md +++ b/@l10n/ru/docs/node/snapshot.md @@ -288,6 +288,7 @@ snapshot-dir = /data/viz-snapshots plugin = snapshot trusted-snapshot-peer = seed1.viz.world:8092 trusted-snapshot-peer = seed2.viz.world:8092 +trusted-snapshot-peer = seed3.viz.world:8092 sync-snapshot-from-trusted-peer = true ``` diff --git a/@l10n/ru/docs/node/validator-guard.md b/@l10n/ru/docs/node/validator-guard.md index c3373ce1c2..0f71387ff1 100644 --- a/@l10n/ru/docs/node/validator-guard.md +++ b/@l10n/ru/docs/node/validator-guard.md @@ -1,6 +1,6 @@ # Защита валидатора (Validator Guard) -Плагин `witness_guard` автоматизирует восстановление ключа подписи для аккаунтов валидаторов. Когда ключ подписи валидатора сбрасывается в null (отключая производство блоков), плагин обнаруживает изменение и транслирует `witness_update_operation` для восстановления ключа — без ручного вмешательства. +Плагин `validator_guard` автоматизирует восстановление ключа подписи для аккаунтов валидаторов. Когда ключ подписи валидатора сбрасывается в null (отключая производство блоков), плагин обнаруживает изменение и транслирует `validator_update_operation` для восстановления ключа — без ручного вмешательства. --- @@ -15,7 +15,7 @@ ## Подключение плагина ```ini -plugin = witness_guard +plugin = validator_guard ``` --- @@ -34,7 +34,7 @@ plugin = witness_guard ### Пример ```ini -plugin = witness_guard +plugin = validator_guard # Мониторинг одного валидатора validator-guard-validator = ["alice", "5K_SIGNING_WIF", "5K_ACTIVE_WIF"] @@ -63,7 +63,7 @@ validator-guard-interval = 10 При каждом блоке: -1. **Автоотключение при последовательных блоках**: Если отслеживаемый валидатор произвёл `validator-guard-disable` последовательных блоков, транслируется `witness_update_operation` с нулевым ключом для его отключения, и валидатор помечается как автоотключённый. Любой блок от *другого* валидатора сбрасывает все счётчики последовательных блоков. +1. **Автоотключение при последовательных блоках**: Если отслеживаемый валидатор произвёл `validator-guard-disable` последовательных блоков, транслируется `validator_update_operation` с нулевым ключом для его отключения, и валидатор помечается как автоотключённый. Любой блок от *другого* валидатора сбрасывает все счётчики последовательных блоков. 2. **Подтверждение транзакции**: Сканирует ожидающие ID транзакций восстановления в блоке. При совпадении помечает восстановление как подтверждённое и очищает состояние отслеживания. 3. **Упреждающее планирование**: Если какой-либо отслеживаемый валидатор запланирован в следующие 3 слота, запускает немедленную проверку, чтобы ключ можно было восстановить до прихода слота. 4. **Периодическая проверка**: В противном случае основная проверка выполняется каждые `validator-guard-interval` блоков. Пока узел всё ещё догоняет после запуска, проверки выполняются каждые 10 блоков. @@ -83,7 +83,7 @@ validator-guard-interval = 10 ### Транзакция восстановления -1. Строит `witness_update_operation`, сохраняя текущий on-chain URL и устанавливая ключ подписи на настроенный публичный ключ. +1. Строит `validator_update_operation`, сохраняя текущий on-chain URL и устанавливая ключ подписи на настроенный публичный ключ. 2. Оборачивает в `signed_transaction` с 30-секундным сроком действия и ссылкой на текущий головной блок. 3. Подписывает настроенным активным приватным ключом. 4. Транслирует через P2P. @@ -113,12 +113,12 @@ validator-guard-interval = 10 | `enable-stale-production detected — auto-restore is DISABLED` | Активен режим устаревшего производства; восстановление подавлено | | `network is healthy (XX%), auto-clearing stale production override` | Защита от устаревшего производства снята | | `'alice' has null signing key on-chain — initiating restore` | Обнаружен нулевой ключ, скоро будет выполнена трансляция | -| `broadcasting witness_update [ID: ...] for 'alice' — restoring key to VIZ...` | Транзакция восстановления отправлена | +| `broadcasting validator_update [ID: ...] for 'alice' — restoring key to VIZ...` | Транзакция восстановления отправлена | | `CONFIRMED restoration for 'alice' in block #N` | Восстановление подтверждено on-chain | | `POTENTIAL LONG FORK DETECTED! LIB #N is Xs old. Skipping restoration.` | Восстановление пропущено из-за устаревшего LIB | | `validator 'alice' produced N consecutive blocks — auto-disabling` | Достигнут порог последовательных блоков | | `'alice' was auto-disabled (consecutive block limit), skipping auto-restore` | Автовосстановление подавлено после автоотключения | -| `witness_update FAILED for 'alice': [error]` | Трансляция не удалась | +| `validator_update FAILED for 'alice': [error]` | Трансляция не удалась | --- diff --git a/@l10n/ru/docs/node/validator-node.md b/@l10n/ru/docs/node/validator-node.md index d2b047ee14..78036c09d2 100644 --- a/@l10n/ru/docs/node/validator-node.md +++ b/@l10n/ru/docs/node/validator-node.md @@ -28,7 +28,7 @@ webserver-http-endpoint = 127.0.0.1:8090 webserver-ws-endpoint = 127.0.0.1:8091 # Обязательные плагины для валидатора -plugin = chain p2p webserver json_rpc database_api network_broadcast_api validator witness_api +plugin = chain p2p webserver json_rpc database_api network_broadcast_api validator validator_api # Пропустить индексирование виртуальных операций для экономии памяти skip-virtual-ops = true @@ -88,11 +88,9 @@ docker run -d \ -v /data/vizd:/var/lib/vizd \ -e VIZD_WITNESS=myvalidator \ -e VIZD_PRIVATE_KEY=5Jxxx... \ - vizblockchain/vizd:lowmem + vizblockchain/vizd:latest ``` -Для валидаторов используйте образ `lowmem` — он не включает ненужные плагины индексирования. - --- ## Регистрация / обновление валидатора @@ -219,7 +217,7 @@ private-key = 5Jyyy... # Ключ Alice.backup emergency-private-key = 5Jzzz... # Ключ экстренного комитета ``` -При его наличии узел автоматически добавляет `CHAIN_EMERGENCY_WITNESS_ACCOUNT` в свой набор валидаторов и участвует в производстве экстренных блоков. См. [Экстренный консенсус](../consensus/emergency-consensus.md). +При его наличии узел автоматически добавляет `CHAIN_EMERGENCY_VALIDATOR_ACCOUNT` в свой набор валидаторов и участвует в производстве экстренных блоков. См. [Экстренный консенсус](../consensus/emergency-consensus.md). --- diff --git a/@l10n/ru/docs/p2p/overview.md b/@l10n/ru/docs/p2p/overview.md index 24bf1ff297..d85d6b8ac4 100644 --- a/@l10n/ru/docs/p2p/overview.md +++ b/@l10n/ru/docs/p2p/overview.md @@ -173,7 +173,7 @@ DLT P2P уровень поддерживает собственный mempool, ## Разрешение форков -DLT P2P уровень отслеживает состояние форка с **порогом 42 блока** (2 полных раунда валидаторов = `CHAIN_MAX_WITNESSES × 2`). +DLT P2P уровень отслеживает состояние форка с **порогом 42 блока** (2 полных раунда валидаторов = `CHAIN_MAX_VALIDATORS × 2`). `track_fork_state()` вызывается после каждого применения блока. При обнаружении конкурирующего форка, удерживаемого ≥ 42 блока, `resolve_fork()` вычисляет **самую весомую ветвь** по общему весу голосов. Ветвь-кандидат должна набрать **6 последовательных блоков подтверждения** (`dlt_fork_resolution_state::CONFIRMATION_BLOCKS`) до переключения узла на неё (гистерезис). diff --git a/@l10n/ru/docs/p2p/stats-reference.md b/@l10n/ru/docs/p2p/stats-reference.md index 85ac9d8c63..bb403cd299 100644 --- a/@l10n/ru/docs/p2p/stats-reference.md +++ b/@l10n/ru/docs/p2p/stats-reference.md @@ -225,7 +225,7 @@ Backoff сбрасывается до начального значения (30 | `GAP_FILL_TIMEOUT_SEC` | 15 | Таймаут флага gap fill в процессе | | `FORWARD_STAGNATION_SEC` | 30 | Порог непродвижения head в режиме FORWARD | | `SYNC_STAGNATION_SEC` | 30 | Порог отсутствия блоков в режиме SYNC | -| `FORK_RESOLUTION_BLOCK_THRESHOLD` | 42 | Блоки до срабатывания разрешения форка (2 × CHAIN_MAX_WITNESSES) | +| `FORK_RESOLUTION_BLOCK_THRESHOLD` | 42 | Блоки до срабатывания разрешения форка (2 × CHAIN_MAX_VALIDATORS) | | `FORK_RESOLUTION_CONFIRMATION_BLOCKS` | 6 | Последовательных блоков для подтверждения разрешения форка | --- diff --git a/@l10n/ru/docs/plugins/database-api.md b/@l10n/ru/docs/plugins/database-api.md index 61c10cbf6b..95674dd9a0 100644 --- a/@l10n/ru/docs/plugins/database-api.md +++ b/@l10n/ru/docs/plugins/database-api.md @@ -95,7 +95,7 @@ json_rpc::plugin, chain::plugin { "method": "database_api.get_dynamic_global_properties", "params": [] } ``` -Ключевые поля: `head_block_number`, `head_block_id`, `time`, `current_witness`, `total_vesting_shares`, `total_vesting_fund_viz`, `committee_fund`, `last_irreversible_block_num`, `participation_count`. +Ключевые поля: `head_block_number`, `head_block_id`, `time`, `current_validator`, `total_vesting_shares`, `total_vesting_fund_viz`, `committee_fund`, `last_irreversible_block_num`, `participation_count`. --- @@ -405,4 +405,4 @@ json_rpc::plugin, chain::plugin --- -См. также: [Обзор плагинов](./overview.md), [Методы witness_api](./overview.md#witness_api), [JSON-RPC API](../api/json-rpc.md). +См. также: [Обзор плагинов](./overview.md), [Методы validator_api](./overview.md#validator_api), [JSON-RPC API](../api/json-rpc.md). diff --git a/@l10n/ru/docs/plugins/overview.md b/@l10n/ru/docs/plugins/overview.md index c6a236ef06..46aefa7b0b 100644 --- a/@l10n/ru/docs/plugins/overview.md +++ b/@l10n/ru/docs/plugins/overview.md @@ -13,7 +13,6 @@ VIZ Ledger использует фреймворк плагинов **AppBase**. | **API** | Предоставляют JSON-RPC эндпоинты для клиентов | | **Индексирование** | Индексируют данные цепочки в chainbase для быстрых запросов | | **Производство** | Подписание и производство блоков | -| **Внешние** | Интеграция с внешними системами (MongoDB) | | **Отладка/Тестирование** | Только для разработки; не для продакшна | --- @@ -34,7 +33,7 @@ VIZ Ledger использует фреймворк плагинов **AppBase**. | `webserver` | Нужен для API | `json_rpc` | — | | `p2p` | Нужен для сети | `chain` | — | | `snapshot` | Рекомендуется | `chain` | — | -| `witness_guard` | Рекомендуется для валидаторов | `chain`, `p2p` | — | +| `validator_guard` | Рекомендуется для валидаторов | `chain`, `p2p` | — | ### API @@ -42,7 +41,7 @@ VIZ Ledger использует фреймворк плагинов **AppBase**. |--------|--------|------------|---------| | `database_api` | Активен | `json_rpc`, `chain` | Да | | `network_broadcast_api` | Активен | `json_rpc`, `chain`, `p2p` | Да | -| `witness_api` | Активен | `json_rpc`, `chain` | Да | +| `validator_api` | Активен | `json_rpc`, `chain` | Да | | `account_by_key` | Активен | `json_rpc`, `chain` | Да | | `account_history` | Активен | `json_rpc`, `chain`, `operation_history` | Да | | `operation_history` | Активен | `json_rpc`, `chain` | Да | @@ -64,12 +63,6 @@ VIZ Ledger использует фреймворк плагинов **AppBase**. |--------|--------|------------|---------| | `validator` | Активен | `chain`, `p2p` | — | -### Внешние - -| Плагин | Статус | Зависимости | JSON-RPC | -|--------|--------|------------|---------| -| `mongo_db` | Активен | `chain` | — | - ### Отладка / Тестирование | Плагин | Статус | Зависимости | JSON-RPC | @@ -196,20 +189,20 @@ DLT P2P-сетевое взаимодействие — распростране --- -### `witness_api` +### `validator_api` Запросы состояния валидаторов: активный набор, расписание, отдельные валидаторы, рейтинги голосов. | Метод | Описание | |-------|---------| -| `get_active_witnesses` | Текущий активный набор из 21 валидатора | -| `get_witness_schedule` | Полный объект расписания | -| `get_witnesses` | Валидаторы по ID в базе данных | -| `get_witness_by_account` | Один валидатор по имени аккаунта | -| `get_witnesses_by_vote` | Валидаторы, отсортированные по суммарному весу голосов | -| `get_witnesses_by_counted_vote` | Валидаторы по числу голосов | -| `get_witness_count` | Общее количество зарегистрированных валидаторов | -| `lookup_witness_accounts` | Список имён аккаунтов валидаторов по префиксу | +| `get_active_validators` | Текущий активный набор из 21 валидатора | +| `get_validator_schedule` | Полный объект расписания | +| `get_validators` | Валидаторы по ID в базе данных | +| `get_validator_by_account` | Один валидатор по имени аккаунта | +| `get_validators_by_vote` | Валидаторы, отсортированные по суммарному весу голосов | +| `get_validators_by_counted_vote` | Валидаторы по числу голосов | +| `get_validator_count` | Общее количество зарегистрированных валидаторов | +| `lookup_validator_accounts` | Список имён аккаунтов валидаторов по префиксу | --- @@ -347,7 +340,7 @@ plugin = webserver plugin = p2p plugin = database_api plugin = network_broadcast_api -plugin = witness_api +plugin = validator_api plugin = account_by_key plugin = account_history plugin = operation_history @@ -366,7 +359,7 @@ plugin = json_rpc plugin = webserver plugin = database_api plugin = network_broadcast_api -plugin = witness_api +plugin = validator_api plugin = snapshot snapshot-every-n-blocks = 28800 diff --git a/@l10n/ru/docs/plugins/snapshot.md b/@l10n/ru/docs/plugins/snapshot.md index 2164104519..dba773c5ae 100644 --- a/@l10n/ru/docs/plugins/snapshot.md +++ b/@l10n/ru/docs/plugins/snapshot.md @@ -286,6 +286,7 @@ snapshot-dir = /data/snapshots plugin = snapshot trusted-snapshot-peer = seed1.viz.world:8092 trusted-snapshot-peer = seed2.viz.world:8092 +trusted-snapshot-peer = seed3.viz.world:8092 sync-snapshot-from-trusted-peer = true ``` diff --git a/@l10n/ru/docs/plugins/validator.md b/@l10n/ru/docs/plugins/validator.md index ea33a9b892..7666743682 100644 --- a/@l10n/ru/docs/plugins/validator.md +++ b/@l10n/ru/docs/plugins/validator.md @@ -22,7 +22,7 @@ chain::plugin, p2p::p2p_plugin, snapshot::snapshot_plugin |---------|------------|---------| | `validator` / `-w` | — | Имя/имена аккаунтов-валидаторов; может повторяться | | `private-key` | — | WIF-ключ(и) для подписи; может повторяться | -| `emergency-private-key` | — | WIF-ключ для экстренного консенсуса; автоматически добавляет `CHAIN_EMERGENCY_WITNESS_ACCOUNT` в набор валидаторов | +| `emergency-private-key` | — | WIF-ключ для экстренного консенсуса; автоматически добавляет `CHAIN_EMERGENCY_VALIDATOR_ACCOUNT` в набор валидаторов | | `enable-stale-production` | `false` | Обход проверок участия и синхронизации (только для тестовой сети / восстановления сети) | | `required-participation` | `3300` | Минимальное участие валидаторов в **базисных пунктах** (3300 = 33%) | | `fork-collision-timeout-blocks` | `21` | Количество последовательных отсрочек при коллизии форков перед принудительным производством (один полный раунд валидаторов) | @@ -175,7 +175,7 @@ Watchdog срабатывает каждые 30 секунд и записыва ### `is_emergency_master()` Возвращает `true`, когда: -1. Настроен `emergency-private-key` (`CHAIN_EMERGENCY_WITNESS_ACCOUNT` в `_witnesses`). +1. Настроен `emergency-private-key` (`CHAIN_EMERGENCY_VALIDATOR_ACCOUNT` в `_validators`). 2. Аккаунт «committee» находится в текущем расписании валидаторов. Только узлы, где выполняются оба условия, должны производить блоки в одиночку в экстренном режиме; остальные являются ведомыми и должны сначала синхронизироваться. diff --git a/@l10n/ru/docs/protocol/data-types.md b/@l10n/ru/docs/protocol/data-types.md index a05a60a979..6f69f0a33e 100644 --- a/@l10n/ru/docs/protocol/data-types.md +++ b/@l10n/ru/docs/protocol/data-types.md @@ -159,9 +159,9 @@ | 3 | `transfer_to_vesting_operation` | | 4 | `withdraw_vesting_operation` | | 5 | `account_update_operation` | -| 6 | `witness_update_operation` | -| 7 | `account_witness_vote_operation` | -| 8 | `account_witness_proxy_operation` | +| 6 | `validator_update_operation` | +| 7 | `account_validator_vote_operation` | +| 8 | `account_validator_proxy_operation` | | 9 | `delete_content_operation` *(устарела)* | | 10 | `custom_operation` | | 11 | `set_withdraw_vesting_route_operation` | @@ -204,7 +204,7 @@ | 27 | `curation_reward_operation` | | 28 | `content_reward_operation` | | 29 | `fill_vesting_withdraw_operation` | -| 30 | `shutdown_witness_operation` | +| 30 | `shutdown_validator_operation` | | 31 | `hardfork_operation` | | 32 | `content_payout_update_operation` | | 33 | `content_benefactor_reward_operation` | @@ -213,7 +213,7 @@ | 39 | `committee_approve_request_operation` | | 40 | `committee_payout_request_operation` | | 41 | `committee_pay_request_operation` | -| 42 | `witness_reward_operation` | +| 42 | `validator_reward_operation` | | 48 | `receive_award_operation` | | 49 | `benefactor_award_operation` | | 52 | `paid_subscription_action_operation` | diff --git a/@l10n/ru/docs/protocol/operations/overview.md b/@l10n/ru/docs/protocol/operations/overview.md index 2379bdcd86..e2dcdb3200 100644 --- a/@l10n/ru/docs/protocol/operations/overview.md +++ b/@l10n/ru/docs/protocol/operations/overview.md @@ -16,9 +16,9 @@ | 3 | `transfer_to_vesting_operation` | active | [Переводы](./transfers.md) | | 4 | `withdraw_vesting_operation` | active | [Переводы](./transfers.md) | | 5 | `account_update_operation` | master / active | [Аккаунты](./accounts.md) | -| 6 | `witness_update_operation` | active | [Валидаторы](./validators.md) | -| 7 | `account_witness_vote_operation` | active | [Валидаторы](./validators.md) | -| 8 | `account_witness_proxy_operation` | active | [Валидаторы](./validators.md) | +| 6 | `validator_update_operation` | active | [Валидаторы](./validators.md) | +| 7 | `account_validator_vote_operation` | active | [Валидаторы](./validators.md) | +| 8 | `account_validator_proxy_operation` | active | [Валидаторы](./validators.md) | | 9 | `delete_content_operation` *(устарела)* | regular | [Контент](./content.md) | | 10 | `custom_operation` | active / regular | [Контент](./content.md) | | 11 | `set_withdraw_vesting_route_operation` | active | [Переводы](./transfers.md) | @@ -65,7 +65,7 @@ | 27 | `curation_reward_operation` | Выплата за контент | [Виртуальные операции](../virtual-operations.md) | | 28 | `content_reward_operation` | Выплата за контент | [Виртуальные операции](../virtual-operations.md) | | 29 | `fill_vesting_withdraw_operation` | Срабатывание интервала вывода | [Виртуальные операции](../virtual-operations.md) | -| 30 | `shutdown_witness_operation` | Деактивация валидатора | [Виртуальные операции](../virtual-operations.md) | +| 30 | `shutdown_validator_operation` | Деактивация валидатора | [Виртуальные операции](../virtual-operations.md) | | 31 | `hardfork_operation` | Активация хардфорка | [Виртуальные операции](../virtual-operations.md) | | 32 | `content_payout_update_operation` | Обновление выплаты за контент | [Виртуальные операции](../virtual-operations.md) | | 33 | `content_benefactor_reward_operation` | Выплата за контент | [Виртуальные операции](../virtual-operations.md) | @@ -74,7 +74,7 @@ | 39 | `committee_approve_request_operation` | Одобрение заявки комитета | [Виртуальные операции](../virtual-operations.md) | | 40 | `committee_payout_request_operation` | Обработка выплаты комитета | [Виртуальные операции](../virtual-operations.md) | | 41 | `committee_pay_request_operation` | Оплата работнику комитета | [Виртуальные операции](../virtual-operations.md) | -| 42 | `witness_reward_operation` | Произведён блок | [Виртуальные операции](../virtual-operations.md) | +| 42 | `validator_reward_operation` | Произведён блок | [Виртуальные операции](../virtual-operations.md) | | 48 | `receive_award_operation` | Получена награда | [Виртуальные операции](../virtual-operations.md) | | 49 | `benefactor_award_operation` | Награда с бенефициаром | [Виртуальные операции](../virtual-operations.md) | | 52 | `paid_subscription_action_operation` | Оплата подписки | [Виртуальные операции](../virtual-operations.md) | diff --git a/@l10n/ru/docs/protocol/operations/validators.md b/@l10n/ru/docs/protocol/operations/validators.md index b8b41cb2c2..845b5363c4 100644 --- a/@l10n/ru/docs/protocol/operations/validators.md +++ b/@l10n/ru/docs/protocol/operations/validators.md @@ -2,7 +2,7 @@ --- -## `witness_update_operation` (ID 6) +## `validator_update_operation` (ID 6) **Авторизация:** `active` `owner` @@ -23,7 +23,7 @@ ``` - **Нулевой ключ** (деактивация): `"VIZ1111111111111111111111111111111114T1Anm"` — удаляет из производства блоков без удаления записи валидатора. -- Трансляция этой операции требует `witness_declaration_fee` (выплачивается в фонд комитета). +- Трансляция этой операции требует `validator_declaration_fee` (выплачивается в фонд комитета). --- @@ -91,18 +91,18 @@ "flag_energy_additional_cost": 1000, "vote_accounting_min_rshares": 0, "committee_request_approve_min_percent": 1000, - "inflation_witness_percent": 2000, + "inflation_validator_percent": 2000, "inflation_ratio_committee_vs_reward_fund": 1000, "inflation_recalc_period": 28800, "data_operations_cost_additional_bandwidth": 0, - "witness_miss_penalty_percent": 100, - "witness_miss_penalty_duration": 86400, + "validator_miss_penalty_percent": 100, + "validator_miss_penalty_duration": 86400, "create_invite_min_balance": "1.000 VIZ", "committee_create_request_fee": "1.000 VIZ", "create_paid_subscription_fee": "1.000 VIZ", "account_on_sale_fee": "10.000 VIZ", "subaccount_on_sale_fee": "1.000 VIZ", - "witness_declaration_fee": "1.000 VIZ", + "validator_declaration_fee": "1.000 VIZ", "withdraw_intervals": 28 }] }] @@ -113,7 +113,7 @@ --- -## `account_witness_vote_operation` (ID 7) +## `account_validator_vote_operation` (ID 7) **Авторизация:** `active` `account` @@ -138,7 +138,7 @@ --- -## `account_witness_proxy_operation` (ID 8) +## `account_validator_proxy_operation` (ID 8) **Авторизация:** `active` `account` diff --git a/@l10n/ru/docs/protocol/virtual-operations.md b/@l10n/ru/docs/protocol/virtual-operations.md index fe1b2790a7..a0d2b158da 100644 --- a/@l10n/ru/docs/protocol/virtual-operations.md +++ b/@l10n/ru/docs/protocol/virtual-operations.md @@ -115,7 +115,7 @@ ## Операции валидатора -### `shutdown_witness_operation` (ID 30) +### `shutdown_validator_operation` (ID 30) **Триггер:** Валидатор деактивирован из-за недостаточного веса голосов @@ -125,7 +125,7 @@ --- -### `witness_reward_operation` (ID 42) +### `validator_reward_operation` (ID 42) **Триггер:** Произведён блок — валидатор получает вознаграждение за блок diff --git a/@l10n/ru/docs/storage/block-log.md b/@l10n/ru/docs/storage/block-log.md index 5fdd02dd98..aa3d264e75 100644 --- a/@l10n/ru/docs/storage/block-log.md +++ b/@l10n/ru/docs/storage/block-log.md @@ -77,7 +77,7 @@ block_header: [varint + vector: extensions] signed_block_header (добавляется): - [65 байт: witness_signature (1 байт восстановления + 32 r + 32 s)] + [65 байт: validator_signature (1 байт восстановления + 32 r + 32 s)] signed_block (добавляется): [varint + vector: транзакции] diff --git a/@l10n/ru/docs/storage/snapshots.md b/@l10n/ru/docs/storage/snapshots.md index cbe54db3c0..e7813df99b 100644 --- a/@l10n/ru/docs/storage/snapshots.md +++ b/@l10n/ru/docs/storage/snapshots.md @@ -208,6 +208,7 @@ snapshot-dir = /data/viz-snapshots ```ini trusted-snapshot-peer = seed1.viz.world:8092 trusted-snapshot-peer = seed2.viz.world:8092 +trusted-snapshot-peer = seed3.viz.world:8092 sync-snapshot-from-trusted-peer = true ``` diff --git a/@l10n/zh-CN/docs/advanced/database-schema.md b/@l10n/zh-CN/docs/advanced/database-schema.md index 7d460724da..7b40df51f1 100644 --- a/@l10n/zh-CN/docs/advanced/database-schema.md +++ b/@l10n/zh-CN/docs/advanced/database-schema.md @@ -48,7 +48,7 @@ VIZ Ledger 使用 ChainBase——一个基于 Boost.Interprocess 构建的内存 账户存储余额、锁仓状态、委托指标、带宽、拍卖/出售标志和治理参与情况。 -**关键字段:** `name`、`balance`(VIZ)、`vesting_shares`、`delegated_vesting_shares`、`received_vesting_shares`、`energy`、`next_vesting_withdrawal`、`witnesses_voted_for`、`recovery_account`。 +**关键字段:** `name`、`balance`(VIZ)、`vesting_shares`、`delegated_vesting_shares`、`received_vesting_shares`、`energy`、`next_vesting_withdrawal`、`validators_voted_for`、`recovery_account`。 **索引:** @@ -94,9 +94,9 @@ VIZ Ledger 使用 ChainBase——一个基于 Boost.Interprocess 构建的内存 --- -## 验证者(Witness)对象 +## 验证者对象 -**`witness_object` 的索引:** +**`validator_object` 的索引:** | 标签 | 键 | |------|-----| diff --git a/@l10n/zh-CN/docs/advanced/dlt-architecture.md b/@l10n/zh-CN/docs/advanced/dlt-architecture.md index d00701855b..92afdb3e6c 100644 --- a/@l10n/zh-CN/docs/advanced/dlt-architecture.md +++ b/@l10n/zh-CN/docs/advanced/dlt-architecture.md @@ -124,7 +124,7 @@ CONNECTING → HANDSHAKING → SYNCING → ACTIVE → DISCONNECTED → BANNED 分叉解决子系统跟踪竞争链的顶端: -- **阈值:** 42 个区块的分歧触发 `resolve_fork()`(= `CHAIN_MAX_WITNESSES × 2`,一个完整的调度轮次)。 +- **阈值:** 42 个区块的分歧触发 `resolve_fork()`(= `CHAIN_MAX_VALIDATORS × 2`,一个完整的调度轮次)。 - **选择:** 按投票权重最重的分支。 - **迟滞:** 切换前需要连续 6 个区块作为赢家(`CONFIRMATION_BLOCKS`)。 - **状态:** `_fork_status` 通过 `is_on_majority_fork()` 暴露,供验证者插件在生产区块前检查。 diff --git a/@l10n/zh-CN/docs/advanced/hardfork-management.md b/@l10n/zh-CN/docs/advanced/hardfork-management.md index 02f1cc0a59..a2dbd920a3 100644 --- a/@l10n/zh-CN/docs/advanced/hardfork-management.md +++ b/@l10n/zh-CN/docs/advanced/hardfork-management.md @@ -57,7 +57,7 @@ HF12 引入了区块生产停滞时的自动网络恢复。 ### 激活 -如果最后一个不可逆区块(LIB)的时间戳比挂钟时间滞后超过 `CHAIN_EMERGENCY_CONSENSUS_TIMEOUT_SEC`(1 小时),紧急模式自动激活。创建一个具有已知公钥(`CHAIN_EMERGENCY_WITNESS_PUBLIC_KEY`)的紧急验证者账户(`CHAIN_EMERGENCY_WITNESS_ACCOUNT = "committee"`),并插入区块生产调度中。 +如果最后一个不可逆区块(LIB)的时间戳比挂钟时间滞后超过 `CHAIN_EMERGENCY_CONSENSUS_TIMEOUT_SEC`(1 小时),紧急模式自动激活。创建一个具有已知公钥(`CHAIN_EMERGENCY_VALIDATOR_PUBLIC_KEY`)的紧急验证者账户(`CHAIN_EMERGENCY_VALIDATOR_ACCOUNT = "committee"`),并插入区块生产调度中。 ### 三态安全执行 diff --git a/@l10n/zh-CN/docs/api/json-rpc.md b/@l10n/zh-CN/docs/api/json-rpc.md index 761e53aa66..cd2d9c6a3e 100644 --- a/@l10n/zh-CN/docs/api/json-rpc.md +++ b/@l10n/zh-CN/docs/api/json-rpc.md @@ -52,7 +52,7 @@ |---------|------|------| | `database_api` | 活跃 | 区块、账户、链状态查询 | | `network_broadcast_api` | 活跃 | 交易和区块广播 | -| `witness_api` | 活跃 | 验证者查询 | +| `validator_api` | 活跃 | 验证者查询 | | `account_by_key` | 活跃 | 反向密钥查找 | | `account_history` | 活跃 | 每账户操作历史 | | `operation_history` | 活跃 | 区块操作查询 | @@ -119,18 +119,18 @@ --- -## `witness_api` 方法 +## `validator_api` 方法 | 方法 | 描述 | |------|------| -| `get_active_witnesses()` | 当前活跃验证者集合(21 个账户) | -| `get_witness_schedule()` | 完整验证者计划对象 | -| `get_witnesses(ids[])` | 按内部 ID 查询验证者 | -| `get_witness_by_account(account)` | 账户的验证者对象 | -| `get_witnesses_by_vote(lower_bound, limit)` | 按投票权重排名的验证者 | -| `get_witnesses_by_counted_vote(lower_bound, limit)` | 按计票排名的验证者 | -| `get_witness_count()` | 已注册验证者总数 | -| `lookup_witness_accounts(lower_bound, limit)` | 列出验证者账户名 | +| `get_active_validators()` | 当前活跃验证者集合(21 个账户) | +| `get_validator_schedule()` | 完整验证者计划对象 | +| `get_validators(ids[])` | 按内部 ID 查询验证者 | +| `get_validator_by_account(account)` | 账户的验证者对象 | +| `get_validators_by_vote(lower_bound, limit)` | 按投票权重排名的验证者 | +| `get_validators_by_counted_vote(lower_bound, limit)` | 按计票排名的验证者 | +| `get_validator_count()` | 已注册验证者总数 | +| `lookup_validator_accounts(lower_bound, limit)` | 列出验证者账户名 | --- @@ -214,7 +214,7 @@ plugin = database_api network_broadcast_api **完整 API 节点(添加):** ```ini -plugin = witness_api account_by_key account_history operation_history +plugin = validator_api account_by_key account_history operation_history plugin = committee_api invite_api paid_subscription_api ``` diff --git a/@l10n/zh-CN/docs/consensus/block-processing.md b/@l10n/zh-CN/docs/consensus/block-processing.md index c3d3cb3eb2..52c6864ce4 100644 --- a/@l10n/zh-CN/docs/consensus/block-processing.md +++ b/@l10n/zh-CN/docs/consensus/block-processing.md @@ -279,7 +279,7 @@ check_block_post_validation_chain(): struct block_post_validation_message { block_id_type block_id; std::string witness_account; // 验证者名称 - signature_type witness_signature; // sign(chain_id + block_id) + signature_type validator_signature; // sign(chain_id + block_id) }; ``` diff --git a/@l10n/zh-CN/docs/consensus/emergency-consensus.md b/@l10n/zh-CN/docs/consensus/emergency-consensus.md index ff4acfeafb..fbfc9a48e6 100644 --- a/@l10n/zh-CN/docs/consensus/emergency-consensus.md +++ b/@l10n/zh-CN/docs/consensus/emergency-consensus.md @@ -9,11 +9,11 @@ | 常量 | 值 | 含义 | |------|---|------| | `CHAIN_EMERGENCY_CONSENSUS_TIMEOUT_SEC` | 3600 秒 | 激活前的不活动时间 | -| `CHAIN_EMERGENCY_WITNESS_ACCOUNT` | `"committee"` | 紧急区块生产者账户 | -| `CHAIN_EMERGENCY_WITNESS_PUBLIC_KEY` | `VIZ75CR...` | 确定性紧急签名密钥 | +| `CHAIN_EMERGENCY_VALIDATOR_ACCOUNT` | `"committee"` | 紧急区块生产者账户 | +| `CHAIN_EMERGENCY_VALIDATOR_PUBLIC_KEY` | `VIZ75CR...` | 确定性紧急签名密钥 | | `CHAIN_EMERGENCY_EXIT_NORMAL_BLOCKS` | 21 | 退出所需的连续真实验证者区块数 | | `CHAIN_IRREVERSIBLE_THRESHOLD` | 75% | 退出所需的计划槽位比例 | -| `CHAIN_MAX_WITNESSES` | 21 | 最大验证者槽位数 | +| `CHAIN_MAX_VALIDATORS` | 21 | 最大验证者槽位数 | ### `dynamic_global_property_object` 中的状态字段 @@ -41,12 +41,12 @@ 1. 设置 `dgp.emergency_consensus_active = true` 和 `dgp.emergency_consensus_start_block = block_num`。 2. 创建或更新"committee"验证者对象: - - `signing_key = CHAIN_EMERGENCY_WITNESS_PUBLIC_KEY` + - `signing_key = CHAIN_EMERGENCY_VALIDATOR_PUBLIC_KEY` - `props = current_median_props` - 硬分叉投票设置为当前应用版本(中性投票者)。 3. 禁用所有真实验证者:设置 `signing_key = zero`,重置 `penalty_percent = 0`,`current_run = 0`。 4. 删除所有 `witness_penalty_expire` 对象。 -5. 覆盖验证者计划:所有 `CHAIN_MAX_WITNESSES` 槽位 → "committee"。 +5. 覆盖验证者计划:所有 `CHAIN_MAX_VALIDATORS` 槽位 → "committee"。 6. 通知 fork DB:`_fork_db.set_emergency_mode(true)`(启用确定性哈希平局决胜)。 7. 日志:`"EMERGENCY CONSENSUS MODE activated at block #N. No blocks for X seconds since LIB Y."` @@ -60,7 +60,7 @@ ```ini # 仅限紧急主节点 -emergency-private-key = 5Jzzz... # CHAIN_EMERGENCY_WITNESS_ACCOUNT 私钥 +emergency-private-key = 5Jzzz... # CHAIN_EMERGENCY_VALIDATOR_ACCOUNT 私钥 ``` | 角色 | DLT 同步检查 | 少数派 fork 检查 | 生产 | @@ -105,7 +105,7 @@ Committee 被排除在硬分叉版本统计和中位链属性计算之外(它 每次计划重建检查退出条件: ``` -real_witness_slots >= CHAIN_MAX_WITNESSES × 75% +real_witness_slots >= CHAIN_MAX_VALIDATORS × 75% ``` 21 个验证者时:`21 × 0.75 = 15.75 → 15` 个真实验证者槽位需要。 @@ -133,7 +133,7 @@ real_witness_slots >= CHAIN_MAX_WITNESSES × 75% ## 验证者守护集成 -`witness_guard` 插件在紧急期间继续运行,实际上更加关键: +`validator_guard` 插件在紧急期间继续运行,实际上更加关键: - 真实验证者在激活时被禁用(签名密钥设为 null)。 - 验证者守护自动广播 `validator_update_operation`,一旦在链上检测到 null 密钥就恢复每个验证者的签名密钥。 @@ -199,7 +199,7 @@ real_witness_slots >= CHAIN_MAX_WITNESSES × 75% | 9 | `stale_sync_check_task` | 主节点头部推进时跳过;从节点卡住时允许 | | 10 | `handle_block` | DLT 紧急中几乎追上的区块视为正常 | | 11 | `database::open` | 启动计划修复 | -| 12 | `witness_guard` | 紧急期间不抑制密钥恢复 | +| 12 | `validator_guard` | 紧急期间不抑制密钥恢复 | | 13 | `snapshot import` | 向前兼容的字段处理 | | 14 | `update_witness_schedule` | 从硬分叉版本统计中排除 committee | | 15 | `update_median_witness_props` | 从中位数计算中排除 committee | diff --git a/@l10n/zh-CN/docs/consensus/fair-dpos.md b/@l10n/zh-CN/docs/consensus/fair-dpos.md index 34cf85a4d3..51498822fa 100644 --- a/@l10n/zh-CN/docs/consensus/fair-dpos.md +++ b/@l10n/zh-CN/docs/consensus/fair-dpos.md @@ -116,8 +116,8 @@ irreversibility_threshold = ceil(num_scheduled_validators * 2 / 3) 如果在 `CHAIN_EMERGENCY_CONSENSUS_TIMEOUT_SEC`(默认 1 小时)内没有生产区块,链切换到**紧急模式**: -- 所有 21 个验证者槽位分配给 `CHAIN_EMERGENCY_WITNESS_ACCOUNT`("committee")。 -- 紧急验证者使用 `CHAIN_EMERGENCY_WITNESS_PUBLIC_KEY` 签名区块。 +- 所有 21 个验证者槽位分配给 `CHAIN_EMERGENCY_VALIDATOR_ACCOUNT`("committee")。 +- 紧急验证者使用 `CHAIN_EMERGENCY_VALIDATOR_PUBLIC_KEY` 签名区块。 - 所有验证者惩罚被重置;已关闭的验证者重新启用。 - 紧急期间 LIB 推进暂停。 - 在 `CHAIN_EMERGENCY_EXIT_NORMAL_BLOCKS`(21)个连续正常区块将 LIB 推进到紧急开始区块之后,紧急模式退出。 @@ -146,7 +146,7 @@ irreversibility_threshold = ceil(num_scheduled_validators * 2 / 3) | `required-participation` | `33`(33%) | 生产区块所需的最低参与度 | | `enable-stale-production` | `false` | 绕过参与度检查(仅限测试网) | | `emergency-private-key` | — | 可选的紧急共识签名密钥 | -| 活跃验证者 | 21 | 在 `CHAIN_MAX_WITNESSES` 中硬编码 | +| 活跃验证者 | 21 | 在 `CHAIN_MAX_VALIDATORS` 中硬编码 | | 区块间隔 | 3 秒 | `CHAIN_BLOCK_INTERVAL` | | LIB 阈值 | ⌈21 × 2/3⌉ = 14 | 确认不可逆性所需的区块数 | | 紧急超时 | 3600 秒 | `CHAIN_EMERGENCY_CONSENSUS_TIMEOUT_SEC` | diff --git a/@l10n/zh-CN/docs/consensus/hardforks.md b/@l10n/zh-CN/docs/consensus/hardforks.md index 15aa75ad7b..30b30cf1e8 100644 --- a/@l10n/zh-CN/docs/consensus/hardforks.md +++ b/@l10n/zh-CN/docs/consensus/hardforks.md @@ -44,7 +44,7 @@ HF13(版本 3.2.0)引入了: **验证者奖励共享**:每个区块的部分验证者奖励按比例重新分配给投票支持该验证者的账户(按其 SHARES 投票权重)。 -- `witness_object` 上的新字段:`reward_percent` — 与投票者共享的区块奖励比例(0–10000 基点)。 +- `validator_object` 上的新字段:`reward_percent` — 与投票者共享的区块奖励比例(0–10000 基点)。 - 新虚拟操作:`validator_reward_virtual_operation` — 每次奖励分配触发一次。 - 通过 `validator_update_operation` 设置。 @@ -121,7 +121,7 @@ case CHAIN_HARDFORK_N: { | 插件 | 需要更新的内容 | |------|-------------| | `account_history` | 为任何新虚拟操作添加影响提取器 | -| `witness_api` | 将 `witness_object` 中的新字段添加到 `witness_api_object` | +| `validator_api` | 将 `validator_object` 中的新字段添加到 `validator_api_object` | | `snapshot` | 将新 chainbase 对象添加到 `serialize_state` / `load_snapshot` | --- @@ -163,7 +163,7 @@ case CHAIN_HARDFORK_N: { - [ ] 所有新字段有零值默认值;`apply_hardfork` 注释解释为何不需要迁移 - [ ] 新评估器在 `initialize_evaluators()` 中注册 - [ ] 新虚拟操作在 `account_history` 插件中注册 -- [ ] 如果 `witness_object` 发生变化,`witness_api_object` 已更新 +- [ ] 如果 `validator_object` 发生变化,`validator_api_object` 已更新 - [ ] 如果添加了新 chainbase 对象,快照插件已更新 --- diff --git a/@l10n/zh-CN/docs/development/building.md b/@l10n/zh-CN/docs/development/building.md index 48b93b9371..f7c1cb5125 100644 --- a/@l10n/zh-CN/docs/development/building.md +++ b/@l10n/zh-CN/docs/development/building.md @@ -113,9 +113,7 @@ build-msvc.bat | Dockerfile | 描述 | |-----------|------| -| `Dockerfile-production` | 完整节点,Release,无 MongoDB | -| `Dockerfile-lowmem` | 同上但启用 `LOW_MEMORY_NODE=ON` | -| `Dockerfile-mongo` | 启用 MongoDB 插件 | +| `Dockerfile-production` | 完整主网节点(Release) | | `Dockerfile-testnet` | Testnet(`BUILD_TESTNET=ON`) | 所有 Dockerfile 使用两阶段构建以最小化镜像大小,并使用 Boost 1.71 包(`libboost-coroutine-dev`、`libboost-context-dev`)。 @@ -129,7 +127,6 @@ build-msvc.bat | `BUILD_TESTNET` | OFF | 为 testnet 构建 | | `LOW_MEMORY_NODE` | OFF | 排除非共识数据(减少 RAM) | | `CHAINBASE_CHECK_LOCKING` | OFF | 启用锁检查(仅用于开发) | -| `ENABLE_MONGO_PLUGIN` | OFF | 包含 MongoDB 插件 | | `BUILD_SHARED_LIBRARIES` | OFF | 构建共享库 | | `USE_PCH` | OFF | 启用预编译头文件(加速重新构建) | diff --git a/@l10n/zh-CN/docs/development/testing.md b/@l10n/zh-CN/docs/development/testing.md index e6c4fcf0d5..3888bf329d 100644 --- a/@l10n/zh-CN/docs/development/testing.md +++ b/@l10n/zh-CN/docs/development/testing.md @@ -128,8 +128,6 @@ CI 矩阵为多种变体构建 Docker 镜像: | 变体 | Dockerfile | |------|-----------| | 标准 | `Dockerfile-production` | -| 低内存 | `Dockerfile-lowmem` | -| MongoDB | `Dockerfile-mongo` | | Testnet | `Dockerfile-testnet` | 按分支和标签触发构建,配置凭据后发布构建产物。 diff --git a/@l10n/zh-CN/docs/governance/chain-properties.md b/@l10n/zh-CN/docs/governance/chain-properties.md index bec0b7b1c5..4ca4e23efa 100644 --- a/@l10n/zh-CN/docs/governance/chain-properties.md +++ b/@l10n/zh-CN/docs/governance/chain-properties.md @@ -41,7 +41,7 @@ ### 3. 应用 -结果 `median_props` 对象存储在 `witness_schedule_object` 中,并在所有区块处理中强制执行。 +结果 `median_props` 对象存储在 `validator_schedule_object` 中,并在所有区块处理中强制执行。 --- @@ -69,11 +69,11 @@ | 属性 | 类型 | 默认值 | 描述 | |------|------|-------|------| -| `inflation_witness_percent` | uint16(bp) | 2000(20%) | 验证者在区块通胀中的份额 | +| `inflation_validator_percent` | uint16(bp) | 2000(20%) | 验证者在区块通胀中的份额 | | `inflation_ratio_committee_vs_reward_fund` | uint16(bp) | 5000(50%) | 剩余通胀的分配:委员会基金 vs 奖励基金 | | `inflation_recalc_period` | uint32(区块) | 806400(~28天) | 通胀重新计算的频率 | -通胀流程:`block_reward × inflation_witness_percent` → 验证者。剩余分配:`inflation_ratio_committee_vs_reward_fund` → 委员会基金;其余 → 奖励基金。 +通胀流程:`block_reward × inflation_validator_percent` → 验证者。剩余分配:`inflation_ratio_committee_vs_reward_fund` → 委员会基金;其余 → 奖励基金。 ### 奖励系统 @@ -88,8 +88,8 @@ | 属性 | 类型 | 默认值 | 描述 | |------|------|-------|------| -| `witness_miss_penalty_percent` | uint16(bp) | 100(1%) | 错过区块时的投票权重降低 | -| `witness_miss_penalty_duration` | uint32(秒) | 86400(1天) | 错过惩罚的持续时间 | +| `validator_miss_penalty_percent` | uint16(bp) | 100(1%) | 错过区块时的投票权重降低 | +| `validator_miss_penalty_duration` | uint32(秒) | 86400(1天) | 错过惩罚的持续时间 | ### 费用 @@ -101,7 +101,7 @@ | `create_paid_subscription_fee` | asset(VIZ) | 100.000 VIZ | 创建付费订阅的费用 | | `account_on_sale_fee` | asset(VIZ) | 10.000 VIZ | 将账户挂牌出售的费用 | | `subaccount_on_sale_fee` | asset(VIZ) | 100.000 VIZ | 将子账户创建权挂牌出售的费用 | -| `witness_declaration_fee` | asset(VIZ) | 10.000 VIZ | 验证者注册的一次性费用 | +| `validator_declaration_fee` | asset(VIZ) | 10.000 VIZ | 验证者注册的一次性费用 | | `create_invite_min_balance` | asset(VIZ) | 10.000 VIZ | 最低邀请余额 | ### 质押提取 @@ -119,9 +119,9 @@ | 版本 | 索引 | 硬分叉 | 新增字段 | |------|------|-------|---------| | `chain_properties_init` | 0 | 创世 | account_creation_fee、maximum_block_size、委托参数、策展、带宽、标记成本、最低 rshares 投票、委员会阈值 | -| `chain_properties_hf4` | 1 | HF4 | inflation_witness_percent、inflation_ratio_committee_vs_reward_fund、inflation_recalc_period | -| `chain_properties_hf6` | 2 | HF6 | data_operations_cost_additional_bandwidth、witness_miss_penalty_percent、witness_miss_penalty_duration | -| `chain_properties_hf9` | 3 | HF9 | create_invite_min_balance、committee_create_request_fee、create_paid_subscription_fee、account_on_sale_fee、subaccount_on_sale_fee、witness_declaration_fee、withdraw_intervals | +| `chain_properties_hf4` | 1 | HF4 | inflation_validator_percent、inflation_ratio_committee_vs_reward_fund、inflation_recalc_period | +| `chain_properties_hf6` | 2 | HF6 | data_operations_cost_additional_bandwidth、validator_miss_penalty_percent、validator_miss_penalty_duration | +| `chain_properties_hf9` | 3 | HF9 | create_invite_min_balance、committee_create_request_fee、create_paid_subscription_fee、account_on_sale_fee、subaccount_on_sale_fee、validator_declaration_fee、withdraw_intervals | 所有新的验证者属性提交请使用版本索引 3(`chain_properties_hf9`)。 diff --git a/@l10n/zh-CN/docs/governance/staking-and-dao.md b/@l10n/zh-CN/docs/governance/staking-and-dao.md index 85064a989e..575e3ff32d 100644 --- a/@l10n/zh-CN/docs/governance/staking-and-dao.md +++ b/@l10n/zh-CN/docs/governance/staking-and-dao.md @@ -75,10 +75,10 @@ SHARES 是通用治理代币。每个有意义的操作都按 `effective_vesting 投票权重在账户投票的所有验证者之间**均等分配**: ``` -fair_weight = effective_vesting_shares / witnesses_voted_for +fair_weight = effective_vesting_shares / validators_voted_for ``` -这防止了集中——为 10 个验证者投票,每人获得你权重的 1/10。账户也可以设置代理(`account_witness_proxy_operation`),将所有验证者投票委托给另一个账户。 +这防止了集中——为 10 个验证者投票,每人获得你权重的 1/10。账户也可以设置代理(`account_validator_proxy_operation`),将所有验证者投票委托给另一个账户。 ### 2. 委员会 DAO 投票 @@ -159,7 +159,7 @@ rshares = effective_vesting_shares × energy / 10000 | `CHAIN_MAX_WITHDRAW_ROUTES` | 10 | 每账户最大提取路由数 | | `CHAIN_ENERGY_REGENERATION_SECONDS` | 432000(5天) | 完全能量恢复时间 | | `CHAIN_100_PERCENT` | 10000 | 基点分母 | -| `CHAIN_MAX_ACCOUNT_WITNESS_VOTES` | 100 | 每账户最大验证者投票数 | +| `CHAIN_MAX_ACCOUNT_VALIDATOR_VOTES` | 100 | 每账户最大验证者投票数 | --- diff --git a/@l10n/zh-CN/docs/introduction/architecture.md b/@l10n/zh-CN/docs/introduction/architecture.md index e1daeba35e..5cbe56dc49 100644 --- a/@l10n/zh-CN/docs/introduction/architecture.md +++ b/@l10n/zh-CN/docs/introduction/architecture.md @@ -57,7 +57,7 @@ VIZ Ledger 实现为一个模块化的 C++ 守护进程(`vizd`),由分层 | `account_by_key` | 按公钥查找账户 | | `follow` | 关注/屏蔽关系索引 | | `tags` | 基于标签的内容索引 | -| `witness_api` | 验证者计划和签名密钥查询 | +| `validator_api` | 验证者计划和签名密钥查询 | | `debug_node` | 测试工具:注入区块、设置时间 | --- diff --git a/@l10n/zh-CN/docs/introduction/key-concepts.md b/@l10n/zh-CN/docs/introduction/key-concepts.md index cf556ca25a..c381542824 100644 --- a/@l10n/zh-CN/docs/introduction/key-concepts.md +++ b/@l10n/zh-CN/docs/introduction/key-concepts.md @@ -76,7 +76,7 @@ VIZ Ledger 上的每个参与者都是一个**账户**。账户持有余额、 与标准 DPOS 不同,VIZ Ledger 对不活跃行为进行惩罚: - 每个验证者都有基于近期区块生产的**参与度评分**。 - 如果全网参与度降至 `required-participation`(默认 33%)以下,区块生产将暂停。 -- 错过过多区块的验证者会受到投票惩罚,惩罚持续 `witness_miss_penalty_duration` 秒。 +- 错过过多区块的验证者会受到投票惩罚,惩罚持续 `validator_miss_penalty_duration` 秒。 --- @@ -89,7 +89,7 @@ VIZ Ledger 上的每个参与者都是一个**账户**。账户持有余额、 - `timestamp`:确切的槽位时间 - `witness`:生产验证者的名称 - `transactions[]`:已签名交易列表 -- `witness_signature`:验证者的签名 +- `validator_signature`:验证者的签名 ### 交易 @@ -112,7 +112,7 @@ VIZ Ledger 上的每个参与者都是一个**账户**。账户持有余额、 | 接收方 | 来源 | |--------|------| -| 验证者 | 区块奖励的 `inflation_witness_percent` | +| 验证者 | 区块奖励的 `inflation_validator_percent` | | 委员会 | `inflation_ratio_committee_vs_reward_fund` 比例 | | 奖励基金 | 余额——通过奖励和内容投票分配 | @@ -146,8 +146,8 @@ VIZ Ledger 上的每个参与者都是一个**账户**。账户持有余额、 关键参数包括: - `account_creation_fee` — 创建新账户的费用 - `maximum_block_size` — 每个区块的最大字节数 -- `inflation_witness_percent` — 验证者的区块奖励份额 -- `witness_miss_penalty_percent` / `witness_miss_penalty_duration` — 错过惩罚 +- `inflation_validator_percent` — 验证者的区块奖励份额 +- `validator_miss_penalty_percent` / `validator_miss_penalty_duration` — 错过惩罚 - `withdraw_intervals` — 质押提取间隔数 参见[链属性治理](../governance/chain-properties.md)查看完整参数列表。 diff --git a/@l10n/zh-CN/docs/node/building.md b/@l10n/zh-CN/docs/node/building.md index c3fdb30992..839144dc0c 100644 --- a/@l10n/zh-CN/docs/node/building.md +++ b/@l10n/zh-CN/docs/node/building.md @@ -126,7 +126,6 @@ build-msvc.bat | `BUILD_TESTNET` | `OFF` | 启用测试网专用代码 | | `LOW_MEMORY_NODE` | `OFF` | 排除历史/索引插件 | | `CHAINBASE_CHECK_LOCKING` | `OFF` | 启用锁断言检查(debug) | -| `ENABLE_MONGO_PLUGIN` | `OFF` | 构建 MongoDB 插件 | | `BUILD_SHARED_LIBRARIES` | `OFF` | 构建共享库 | | `USE_PCH` | `OFF` | 启用预编译头文件(加快重新构建) | @@ -165,8 +164,6 @@ python3 programs/build_helpers/configure_build.py --release | 文件 | 用途 | |------|------| | `Dockerfile-production` | 完整主网节点(Release) | -| `Dockerfile-lowmem` | 低内存节点(`LOW_MEMORY_NODE=ON`) | -| `Dockerfile-mongo` | 含 MongoDB 插件的节点 | | `Dockerfile-testnet` | 测试网节点(`BUILD_TESTNET=ON`) | 构建示例: diff --git a/@l10n/zh-CN/docs/node/configuration.md b/@l10n/zh-CN/docs/node/configuration.md index 504f2dd8b8..5d237db45e 100644 --- a/@l10n/zh-CN/docs/node/configuration.md +++ b/@l10n/zh-CN/docs/node/configuration.md @@ -7,8 +7,6 @@ VIZ Ledger 节点通过 INI 文件进行配置。仓库在 `share/vizd/config/` | `config.ini` | 带公共 RPC 的完整主网节点 | | `config_witness.ini` | 验证者节点(本地 RPC,区块生产) | | `config_testnet.ini` | 测试网/开发环境 | -| `config_mongo.ini` | 带 MongoDB 历史后端的节点 | -| `config_lowmem.ini` | 低内存共识/种子节点 | | `config_stock_exchange.ini` | 市场数据消费者(最少插件) | | `config_debug.ini` | 调试模式 | @@ -26,6 +24,7 @@ p2p-max-connections = 200 # 引导连接的种子节点(可重复) p2p-seed-node = seed1.viz.world:2001 p2p-seed-node = seed2.viz.world:2001 +p2p-seed-node = seed3.viz.world:2001 # 检查点:受信任的 (block_num, block_id) 对(可重复) # checkpoint = [12345,"0003039..." ] @@ -112,7 +111,7 @@ plugin = social_network tags follow account_history account_by_key plugin = committee_api invite_api paid_subscription_api custom_protocol_api # 仅用于验证者节点: -plugin = validator witness_api +plugin = validator validator_api ``` ### 按节点类型划分的插件集 @@ -120,7 +119,7 @@ plugin = validator witness_api | 节点类型 | 插件 | |---------|------| | 全节点 | 以上所有 | -| 验证者 | `chain p2p webserver json_rpc database_api network_broadcast_api validator witness_api` | +| 验证者 | `chain p2p webserver json_rpc database_api network_broadcast_api validator validator_api` | | 低内存种子 | `chain p2p` | | 交易所 | `chain p2p webserver json_rpc database_api network_broadcast_api account_history` | @@ -198,17 +197,6 @@ logger.p2p.appenders = p2p --- -## MongoDB(可选) - -仅当节点使用 `ENABLE_MONGO_PLUGIN=ON` 构建时有效: - -```ini -plugin = mongo_db -mongodb-uri = mongodb://localhost:27017/vizd -``` - ---- - ## 完整参考 按源文件列出的所有选项: diff --git a/@l10n/zh-CN/docs/node/docker.md b/@l10n/zh-CN/docs/node/docker.md index c86e4c854d..6f07980174 100644 --- a/@l10n/zh-CN/docs/node/docker.md +++ b/@l10n/zh-CN/docs/node/docker.md @@ -9,8 +9,6 @@ VIZ Ledger 提供四种 Docker 镜像,适用于不同的部署场景。所有 | Dockerfile | 标签 | 描述 | |-----------|-----|------| | `Dockerfile-production` | `latest` | 完整主网节点(Release,全部插件) | -| `Dockerfile-lowmem` | `lowmem` | 低内存节点(`LOW_MEMORY_NODE=ON`,无历史索引) | -| `Dockerfile-mongo` | `mongo` | 含 MongoDB 历史插件的完整节点 | | `Dockerfile-testnet` | `testnet` | 测试网节点(`BUILD_TESTNET=ON`) | --- @@ -62,7 +60,7 @@ docker run -d \ | 变量 | 描述 | 示例 | |------|------|------| -| `VIZD_SEED_NODES` | 空格分隔的种子节点列表(覆盖 `/etc/vizd/seednodes`) | `seed1.viz.world:2001 seed2.viz.world:2001` | +| `VIZD_SEED_NODES` | 空格分隔的种子节点列表(覆盖 `/etc/vizd/seednodes`) | `seed1.viz.world:2001 seed2.viz.world:2001 seed3.viz.world:2001` | | `VIZD_RPC_ENDPOINT` | 覆盖 HTTP RPC 端点 | `0.0.0.0:8090` | | `VIZD_P2P_ENDPOINT` | 覆盖 P2P 端点 | `0.0.0.0:2001` | | `VIZD_WITNESS` | 验证者账户名(启用区块生产) | `alice` | @@ -123,21 +121,19 @@ docker build \ -t vizd:local \ . -# Low-memory +# Testnet docker build \ - -f share/vizd/docker/Dockerfile-lowmem \ - -t vizd:lowmem \ + -f share/vizd/docker/Dockerfile-testnet \ + -t vizd:testnet \ . ``` ### 各镜像的 CMake 标志 -| 镜像 | `LOW_MEMORY_NODE` | `ENABLE_MONGO_PLUGIN` | `BUILD_TESTNET` | -|------|:-----------------:|:---------------------:|:---------------:| -| production | OFF | OFF | OFF | -| lowmem | ON | OFF | OFF | -| mongo | OFF | ON | OFF | -| testnet | OFF | OFF | ON | +| 镜像 | `LOW_MEMORY_NODE` | `BUILD_TESTNET` | +|------|:-----------------:|:---------------:| +| production | OFF | OFF | +| testnet | OFF | ON | --- @@ -161,7 +157,7 @@ docker build \ | 节点类型 | 内存 | 磁盘 | |---------|------|------| | 完整节点(主网) | 8 GB+ | 50 GB+ | -| 低内存 / 验证者 | 4 GB | 20 GB | +| 验证者节点 | 4 GB | 20 GB | | 测试网 | 4 GB | 10 GB | 共享内存大小应能舒适地放入 RAM。在 `config.ini` 中: diff --git a/@l10n/zh-CN/docs/node/getting-started.md b/@l10n/zh-CN/docs/node/getting-started.md index 7ee284cda3..ab96b918ed 100644 --- a/@l10n/zh-CN/docs/node/getting-started.md +++ b/@l10n/zh-CN/docs/node/getting-started.md @@ -122,6 +122,7 @@ cp share/vizd/config/config.ini /data/vizd/config.ini p2p-endpoint = 0.0.0.0:2001 p2p-seed-node = seed1.viz.world:2001 p2p-seed-node = seed2.viz.world:2001 +p2p-seed-node = seed3.viz.world:2001 # RPC webserver-http-endpoint = 0.0.0.0:8090 @@ -172,7 +173,6 @@ curl -s -X POST http://localhost:8090 \ | 验证者 | `config_witness.ini` | 区块生产,RPC 仅限本地 | | 测试网 | `config_testnet.ini` | 开发和测试 | | 低内存 | `config.ini` + `LOW_MEMORY_NODE` 构建标志 | 仅共识,无历史索引 | -| MongoDB | `config_mongo.ini` | MongoDB 中的完整历史 | --- diff --git a/@l10n/zh-CN/docs/node/snapshot.md b/@l10n/zh-CN/docs/node/snapshot.md index 05fc469c64..15155ece3a 100644 --- a/@l10n/zh-CN/docs/node/snapshot.md +++ b/@l10n/zh-CN/docs/node/snapshot.md @@ -288,6 +288,7 @@ snapshot-dir = /data/viz-snapshots plugin = snapshot trusted-snapshot-peer = seed1.viz.world:8092 trusted-snapshot-peer = seed2.viz.world:8092 +trusted-snapshot-peer = seed3.viz.world:8092 sync-snapshot-from-trusted-peer = true ``` diff --git a/@l10n/zh-CN/docs/node/validator-guard.md b/@l10n/zh-CN/docs/node/validator-guard.md index f1fbd896e6..23697f0eac 100644 --- a/@l10n/zh-CN/docs/node/validator-guard.md +++ b/@l10n/zh-CN/docs/node/validator-guard.md @@ -1,6 +1,6 @@ # 验证者守护(Validator Guard) -`witness_guard` 插件为验证者账户自动化签名密钥恢复。当验证者的签名密钥被重置为 null(禁用区块生产)时,插件检测到此变化并广播 `witness_update_operation` 以恢复密钥——无需手动干预。 +`validator_guard` 插件为验证者账户自动化签名密钥恢复。当验证者的签名密钥被重置为 null(禁用区块生产)时,插件检测到此变化并广播 `validator_update_operation` 以恢复密钥——无需手动干预。 --- @@ -15,7 +15,7 @@ ## 启用插件 ```ini -plugin = witness_guard +plugin = validator_guard ``` --- @@ -34,7 +34,7 @@ plugin = witness_guard ### 示例 ```ini -plugin = witness_guard +plugin = validator_guard # 监控一个验证者 validator-guard-validator = ["alice", "5K_SIGNING_WIF", "5K_ACTIVE_WIF"] @@ -63,7 +63,7 @@ validator-guard-interval = 10 每个区块时: -1. **连续区块自动禁用**:如果被监控的验证者连续生产了 `validator-guard-disable` 个区块,广播带 null 密钥的 `witness_update_operation` 以禁用它,并将该验证者标记为自动禁用。*其他*验证者的任何区块都会重置所有连续计数器。 +1. **连续区块自动禁用**:如果被监控的验证者连续生产了 `validator-guard-disable` 个区块,广播带 null 密钥的 `validator_update_operation` 以禁用它,并将该验证者标记为自动禁用。*其他*验证者的任何区块都会重置所有连续计数器。 2. **交易确认**:扫描区块中待处理的恢复交易 ID。匹配时,将恢复标记为已确认并清除跟踪状态。 3. **前瞻调度**:如果任何被监控的验证者在接下来的 3 个槽位内有安排,触发立即检查,以便在槽位到来前恢复密钥。 4. **周期性检查**:否则,每 `validator-guard-interval` 个区块运行核心检查。节点启动后仍在追赶时,每 10 个区块检查一次。 @@ -83,7 +83,7 @@ validator-guard-interval = 10 ### 恢复交易 -1. 构建 `witness_update_operation`,保留当前链上 URL,并将签名密钥设置为配置的公钥。 +1. 构建 `validator_update_operation`,保留当前链上 URL,并将签名密钥设置为配置的公钥。 2. 包装为 `signed_transaction`,30 秒到期时间,引用当前头块。 3. 使用配置的活跃私钥签名。 4. 通过 P2P 广播。 @@ -113,12 +113,12 @@ validator-guard-interval = 10 | `enable-stale-production detected — auto-restore is DISABLED` | 过时生产模式激活;恢复被抑制 | | `network is healthy (XX%), auto-clearing stale production override` | 过时生产防护已解除 | | `'alice' has null signing key on-chain — initiating restore` | 检测到 null 密钥,即将广播 | -| `broadcasting witness_update [ID: ...] for 'alice' — restoring key to VIZ...` | 恢复交易已发送 | +| `broadcasting validator_update [ID: ...] for 'alice' — restoring key to VIZ...` | 恢复交易已发送 | | `CONFIRMED restoration for 'alice' in block #N` | 恢复已在链上确认 | | `POTENTIAL LONG FORK DETECTED! LIB #N is Xs old. Skipping restoration.` | 由于 LIB 过期而跳过恢复 | | `validator 'alice' produced N consecutive blocks — auto-disabling` | 连续区块阈值已达到 | | `'alice' was auto-disabled (consecutive block limit), skipping auto-restore` | 自动禁用后抑制自动恢复 | -| `witness_update FAILED for 'alice': [error]` | 广播失败 | +| `validator_update FAILED for 'alice': [error]` | 广播失败 | --- diff --git a/@l10n/zh-CN/docs/node/validator-node.md b/@l10n/zh-CN/docs/node/validator-node.md index 2674492313..26ae1c8257 100644 --- a/@l10n/zh-CN/docs/node/validator-node.md +++ b/@l10n/zh-CN/docs/node/validator-node.md @@ -28,7 +28,7 @@ webserver-http-endpoint = 127.0.0.1:8090 webserver-ws-endpoint = 127.0.0.1:8091 # 验证者所需插件 -plugin = chain p2p webserver json_rpc database_api network_broadcast_api validator witness_api +plugin = chain p2p webserver json_rpc database_api network_broadcast_api validator validator_api # 跳过虚拟操作索引以节省内存 skip-virtual-ops = true @@ -88,11 +88,9 @@ docker run -d \ -v /data/vizd:/var/lib/vizd \ -e VIZD_WITNESS=myvalidator \ -e VIZD_PRIVATE_KEY=5Jxxx... \ - vizblockchain/vizd:lowmem + vizblockchain/vizd:latest ``` -验证者请使用 `lowmem` 镜像——它不含不必要的索引插件。 - --- ## 注册/更新验证者 @@ -219,7 +217,7 @@ private-key = 5Jyyy... # Alice.backup 的密钥 emergency-private-key = 5Jzzz... # 委员会紧急密钥 ``` -设置后,节点自动将 `CHAIN_EMERGENCY_WITNESS_ACCOUNT` 添加到其验证者集合,并参与紧急区块生产。参见[紧急共识](../consensus/emergency-consensus.md)。 +设置后,节点自动将 `CHAIN_EMERGENCY_VALIDATOR_ACCOUNT` 添加到其验证者集合,并参与紧急区块生产。参见[紧急共识](../consensus/emergency-consensus.md)。 --- diff --git a/@l10n/zh-CN/docs/p2p/overview.md b/@l10n/zh-CN/docs/p2p/overview.md index d206298b3e..addf8b4bbe 100644 --- a/@l10n/zh-CN/docs/p2p/overview.md +++ b/@l10n/zh-CN/docs/p2p/overview.md @@ -171,7 +171,7 @@ DLT P2P 层维护自己的 mempool,独立于链的 `_pending_tx`。这允许 ## Fork 解决 -DLT P2P 层以 **42 区块阈值**(2 个完整验证者轮次 = `CHAIN_MAX_WITNESSES × 2`)跟踪 fork 状态。 +DLT P2P 层以 **42 区块阈值**(2 个完整验证者轮次 = `CHAIN_MAX_VALIDATORS × 2`)跟踪 fork 状态。 `track_fork_state()` 在每次区块应用后被调用。当检测到持续 ≥ 42 个区块的竞争 fork 时,`resolve_fork()` 通过总投票权重计算**最重的分支**。候选分支必须积累 **6 个连续确认区块**(`dlt_fork_resolution_state::CONFIRMATION_BLOCKS`)才能切换节点(滞后效应)。 diff --git a/@l10n/zh-CN/docs/p2p/stats-reference.md b/@l10n/zh-CN/docs/p2p/stats-reference.md index 5faeef439e..36a698b9a9 100644 --- a/@l10n/zh-CN/docs/p2p/stats-reference.md +++ b/@l10n/zh-CN/docs/p2p/stats-reference.md @@ -225,7 +225,7 @@ DLT Status | FORWARD | head=#79881136 lib=#79881130 | dlt_range=79000000-7988113 | `GAP_FILL_TIMEOUT_SEC` | 15 | 间隙填补进行中标志超时 | | `FORWARD_STAGNATION_SEC` | 30 | FORWARD 模式下 head 不前进阈值 | | `SYNC_STAGNATION_SEC` | 30 | SYNC 模式下未收到区块阈值 | -| `FORK_RESOLUTION_BLOCK_THRESHOLD` | 42 | 触发 fork 解决前的区块数(2 × CHAIN_MAX_WITNESSES) | +| `FORK_RESOLUTION_BLOCK_THRESHOLD` | 42 | 触发 fork 解决前的区块数(2 × CHAIN_MAX_VALIDATORS) | | `FORK_RESOLUTION_CONFIRMATION_BLOCKS` | 6 | 确认 fork 解决的连续区块数 | --- diff --git a/@l10n/zh-CN/docs/plugins/database-api.md b/@l10n/zh-CN/docs/plugins/database-api.md index 004ddd10e7..1865f43070 100644 --- a/@l10n/zh-CN/docs/plugins/database-api.md +++ b/@l10n/zh-CN/docs/plugins/database-api.md @@ -95,7 +95,7 @@ json_rpc::plugin, chain::plugin { "method": "database_api.get_dynamic_global_properties", "params": [] } ``` -关键字段:`head_block_number`、`head_block_id`、`time`、`current_witness`、`total_vesting_shares`、`total_vesting_fund_viz`、`committee_fund`、`last_irreversible_block_num`、`participation_count`。 +关键字段:`head_block_number`、`head_block_id`、`time`、`current_validator`、`total_vesting_shares`、`total_vesting_fund_viz`、`committee_fund`、`last_irreversible_block_num`、`participation_count`。 --- @@ -405,4 +405,4 @@ json_rpc::plugin, chain::plugin --- -参见:[插件概述](./overview.md)、[witness_api 方法](./overview.md#witness_api)、[JSON-RPC API](../api/json-rpc.md)。 +参见:[插件概述](./overview.md)、[validator_api 方法](./overview.md#validator_api)、[JSON-RPC API](../api/json-rpc.md)。 diff --git a/@l10n/zh-CN/docs/plugins/overview.md b/@l10n/zh-CN/docs/plugins/overview.md index a9d593c611..24e00071e6 100644 --- a/@l10n/zh-CN/docs/plugins/overview.md +++ b/@l10n/zh-CN/docs/plugins/overview.md @@ -13,7 +13,6 @@ VIZ Ledger 使用 **AppBase** 插件框架。每个插件都有生命周期(`p | **API** | 为客户端公开 JSON-RPC 端点 | | **索引** | 将链数据索引到 chainbase 以进行快速查询 | | **生产** | 区块签名和生产 | -| **外部** | 与外部系统集成(MongoDB) | | **调试/测试** | 仅用于开发;不用于生产 | --- @@ -34,7 +33,7 @@ VIZ Ledger 使用 **AppBase** 插件框架。每个插件都有生命周期(`p | `webserver` | API 必需 | `json_rpc` | — | | `p2p` | 网络必需 | `chain` | — | | `snapshot` | 推荐 | `chain` | — | -| `witness_guard` | 验证者推荐 | `chain`, `p2p` | — | +| `validator_guard` | 验证者推荐 | `chain`, `p2p` | — | ### API @@ -42,7 +41,7 @@ VIZ Ledger 使用 **AppBase** 插件框架。每个插件都有生命周期(`p |------|------|------|---------| | `database_api` | 活跃 | `json_rpc`, `chain` | 是 | | `network_broadcast_api` | 活跃 | `json_rpc`, `chain`, `p2p` | 是 | -| `witness_api` | 活跃 | `json_rpc`, `chain` | 是 | +| `validator_api` | 活跃 | `json_rpc`, `chain` | 是 | | `account_by_key` | 活跃 | `json_rpc`, `chain` | 是 | | `account_history` | 活跃 | `json_rpc`, `chain`, `operation_history` | 是 | | `operation_history` | 活跃 | `json_rpc`, `chain` | 是 | @@ -64,12 +63,6 @@ VIZ Ledger 使用 **AppBase** 插件框架。每个插件都有生命周期(`p |------|------|------|---------| | `validator` | 活跃 | `chain`, `p2p` | — | -### 外部 - -| 插件 | 状态 | 依赖 | JSON-RPC | -|------|------|------|---------| -| `mongo_db` | 活跃 | `chain` | — | - ### 调试/测试 | 插件 | 状态 | 依赖 | JSON-RPC | @@ -196,20 +189,20 @@ DLT P2P 网络——区块和交易传播、节点管理、少数派 fork 恢复 --- -### `witness_api` +### `validator_api` 查询验证者状态:活跃集合、计划、单个验证者、投票排名。 | 方法 | 描述 | |------|------| -| `get_active_witnesses` | 当前 21 验证者活跃集合 | -| `get_witness_schedule` | 完整计划对象 | -| `get_witnesses` | 按数据库 ID 查询验证者 | -| `get_witness_by_account` | 按账户名查询单个验证者 | -| `get_witnesses_by_vote` | 按总投票权重排序的验证者 | -| `get_witnesses_by_counted_vote` | 按计票权重排序的验证者 | -| `get_witness_count` | 已注册验证者总数 | -| `lookup_witness_accounts` | 按前缀列出验证者账户名 | +| `get_active_validators` | 当前 21 验证者活跃集合 | +| `get_validator_schedule` | 完整计划对象 | +| `get_validators` | 按数据库 ID 查询验证者 | +| `get_validator_by_account` | 按账户名查询单个验证者 | +| `get_validators_by_vote` | 按总投票权重排序的验证者 | +| `get_validators_by_counted_vote` | 按计票权重排序的验证者 | +| `get_validator_count` | 已注册验证者总数 | +| `lookup_validator_accounts` | 按前缀列出验证者账户名 | --- @@ -347,7 +340,7 @@ plugin = webserver plugin = p2p plugin = database_api plugin = network_broadcast_api -plugin = witness_api +plugin = validator_api plugin = account_by_key plugin = account_history plugin = operation_history @@ -366,7 +359,7 @@ plugin = json_rpc plugin = webserver plugin = database_api plugin = network_broadcast_api -plugin = witness_api +plugin = validator_api plugin = snapshot snapshot-every-n-blocks = 28800 diff --git a/@l10n/zh-CN/docs/plugins/snapshot.md b/@l10n/zh-CN/docs/plugins/snapshot.md index e56b9bf2dd..a7b90874db 100644 --- a/@l10n/zh-CN/docs/plugins/snapshot.md +++ b/@l10n/zh-CN/docs/plugins/snapshot.md @@ -286,6 +286,7 @@ snapshot-dir = /data/snapshots plugin = snapshot trusted-snapshot-peer = seed1.viz.world:8092 trusted-snapshot-peer = seed2.viz.world:8092 +trusted-snapshot-peer = seed3.viz.world:8092 sync-snapshot-from-trusted-peer = true ``` diff --git a/@l10n/zh-CN/docs/plugins/validator.md b/@l10n/zh-CN/docs/plugins/validator.md index 558eacfa55..1b8ee701de 100644 --- a/@l10n/zh-CN/docs/plugins/validator.md +++ b/@l10n/zh-CN/docs/plugins/validator.md @@ -22,7 +22,7 @@ chain::plugin, p2p::p2p_plugin, snapshot::snapshot_plugin |------|-------|------| | `validator` / `-w` | — | 验证者账户名;可重复 | | `private-key` | — | 用于签名的 WIF 私钥;可重复 | -| `emergency-private-key` | — | 紧急共识的 WIF 密钥;自动将 `CHAIN_EMERGENCY_WITNESS_ACCOUNT` 添加到验证者集合 | +| `emergency-private-key` | — | 紧急共识的 WIF 密钥;自动将 `CHAIN_EMERGENCY_VALIDATOR_ACCOUNT` 添加到验证者集合 | | `enable-stale-production` | `false` | 绕过参与度和同步检查(仅用于测试网/网络恢复) | | `required-participation` | `3300` | 最低验证者参与度(**基点**,3300 = 33%) | | `fork-collision-timeout-blocks` | `21` | 强制生产前的连续 fork 冲突延迟次数(一个完整的验证者轮次) | @@ -175,7 +175,7 @@ Watchdog 每 30 秒触发一次并记录诊断。如果满足恢复条件(头 ### `is_emergency_master()` 在以下条件下返回 `true`: -1. 已配置 `emergency-private-key`(`_witnesses` 中的 `CHAIN_EMERGENCY_WITNESS_ACCOUNT`)。 +1. 已配置 `emergency-private-key`(`_validators` 中的 `CHAIN_EMERGENCY_VALIDATOR_ACCOUNT`)。 2. "committee" 账户在当前验证者计划中。 只有满足两个条件的节点才应在紧急模式下独自生产;其他节点是从属节点,必须先同步。 diff --git a/@l10n/zh-CN/docs/protocol/data-types.md b/@l10n/zh-CN/docs/protocol/data-types.md index 4086ac3670..3aa2f93d05 100644 --- a/@l10n/zh-CN/docs/protocol/data-types.md +++ b/@l10n/zh-CN/docs/protocol/data-types.md @@ -159,9 +159,9 @@ VIZ Ledger 协议操作和虚拟操作中使用的所有共享数据类型。 | 3 | `transfer_to_vesting_operation` | | 4 | `withdraw_vesting_operation` | | 5 | `account_update_operation` | -| 6 | `witness_update_operation` | -| 7 | `account_witness_vote_operation` | -| 8 | `account_witness_proxy_operation` | +| 6 | `validator_update_operation` | +| 7 | `account_validator_vote_operation` | +| 8 | `account_validator_proxy_operation` | | 9 | `delete_content_operation` *(已弃用)* | | 10 | `custom_operation` | | 11 | `set_withdraw_vesting_route_operation` | @@ -204,7 +204,7 @@ VIZ Ledger 协议操作和虚拟操作中使用的所有共享数据类型。 | 27 | `curation_reward_operation` | | 28 | `content_reward_operation` | | 29 | `fill_vesting_withdraw_operation` | -| 30 | `shutdown_witness_operation` | +| 30 | `shutdown_validator_operation` | | 31 | `hardfork_operation` | | 32 | `content_payout_update_operation` | | 33 | `content_benefactor_reward_operation` | @@ -213,7 +213,7 @@ VIZ Ledger 协议操作和虚拟操作中使用的所有共享数据类型。 | 39 | `committee_approve_request_operation` | | 40 | `committee_payout_request_operation` | | 41 | `committee_pay_request_operation` | -| 42 | `witness_reward_operation` | +| 42 | `validator_reward_operation` | | 48 | `receive_award_operation` | | 49 | `benefactor_award_operation` | | 52 | `paid_subscription_action_operation` | diff --git a/@l10n/zh-CN/docs/protocol/operations/overview.md b/@l10n/zh-CN/docs/protocol/operations/overview.md index fe92296ae7..602109cc12 100644 --- a/@l10n/zh-CN/docs/protocol/operations/overview.md +++ b/@l10n/zh-CN/docs/protocol/operations/overview.md @@ -16,9 +16,9 @@ VIZ Ledger 操作是包含在交易中的原子状态变更动作。每个操作 | 3 | `transfer_to_vesting_operation` | active | [转账](./transfers.md) | | 4 | `withdraw_vesting_operation` | active | [转账](./transfers.md) | | 5 | `account_update_operation` | master / active | [账户](./accounts.md) | -| 6 | `witness_update_operation` | active | [验证者](./validators.md) | -| 7 | `account_witness_vote_operation` | active | [验证者](./validators.md) | -| 8 | `account_witness_proxy_operation` | active | [验证者](./validators.md) | +| 6 | `validator_update_operation` | active | [验证者](./validators.md) | +| 7 | `account_validator_vote_operation` | active | [验证者](./validators.md) | +| 8 | `account_validator_proxy_operation` | active | [验证者](./validators.md) | | 9 | `delete_content_operation` *(已弃用)* | regular | [内容](./content.md) | | 10 | `custom_operation` | active / regular | [内容](./content.md) | | 11 | `set_withdraw_vesting_route_operation` | active | [转账](./transfers.md) | @@ -65,7 +65,7 @@ VIZ Ledger 操作是包含在交易中的原子状态变更动作。每个操作 | 27 | `curation_reward_operation` | 内容支付 | [虚拟操作](../virtual-operations.md) | | 28 | `content_reward_operation` | 内容支付 | [虚拟操作](../virtual-operations.md) | | 29 | `fill_vesting_withdraw_operation` | 提取间隔触发 | [虚拟操作](../virtual-operations.md) | -| 30 | `shutdown_witness_operation` | 验证者停用 | [虚拟操作](../virtual-operations.md) | +| 30 | `shutdown_validator_operation` | 验证者停用 | [虚拟操作](../virtual-operations.md) | | 31 | `hardfork_operation` | 硬分叉激活 | [虚拟操作](../virtual-operations.md) | | 32 | `content_payout_update_operation` | 内容支付更新 | [虚拟操作](../virtual-operations.md) | | 33 | `content_benefactor_reward_operation` | 内容支付 | [虚拟操作](../virtual-operations.md) | @@ -74,7 +74,7 @@ VIZ Ledger 操作是包含在交易中的原子状态变更动作。每个操作 | 39 | `committee_approve_request_operation` | 委员会请求获批 | [虚拟操作](../virtual-operations.md) | | 40 | `committee_payout_request_operation` | 委员会支付处理 | [虚拟操作](../virtual-operations.md) | | 41 | `committee_pay_request_operation` | 委员会工作者已付款 | [虚拟操作](../virtual-operations.md) | -| 42 | `witness_reward_operation` | 区块已生产 | [虚拟操作](../virtual-operations.md) | +| 42 | `validator_reward_operation` | 区块已生产 | [虚拟操作](../virtual-operations.md) | | 48 | `receive_award_operation` | 奖励已接收 | [虚拟操作](../virtual-operations.md) | | 49 | `benefactor_award_operation` | 带受益人的奖励 | [虚拟操作](../virtual-operations.md) | | 52 | `paid_subscription_action_operation` | 订阅支付 | [虚拟操作](../virtual-operations.md) | diff --git a/@l10n/zh-CN/docs/protocol/operations/validators.md b/@l10n/zh-CN/docs/protocol/operations/validators.md index e4893df7f4..7c83b51228 100644 --- a/@l10n/zh-CN/docs/protocol/operations/validators.md +++ b/@l10n/zh-CN/docs/protocol/operations/validators.md @@ -2,7 +2,7 @@ --- -## `witness_update_operation`(ID 6) +## `validator_update_operation`(ID 6) **授权:** `owner` 的 `active` @@ -23,7 +23,7 @@ ``` - **空密钥**(停用):`"VIZ1111111111111111111111111111111114T1Anm"` — 从区块生产中移除,不删除验证者记录。 -- 广播此操作需要 `witness_declaration_fee`(支付到委员会基金)。 +- 广播此操作需要 `validator_declaration_fee`(支付到委员会基金)。 --- @@ -91,18 +91,18 @@ "flag_energy_additional_cost": 1000, "vote_accounting_min_rshares": 0, "committee_request_approve_min_percent": 1000, - "inflation_witness_percent": 2000, + "inflation_validator_percent": 2000, "inflation_ratio_committee_vs_reward_fund": 1000, "inflation_recalc_period": 28800, "data_operations_cost_additional_bandwidth": 0, - "witness_miss_penalty_percent": 100, - "witness_miss_penalty_duration": 86400, + "validator_miss_penalty_percent": 100, + "validator_miss_penalty_duration": 86400, "create_invite_min_balance": "1.000 VIZ", "committee_create_request_fee": "1.000 VIZ", "create_paid_subscription_fee": "1.000 VIZ", "account_on_sale_fee": "10.000 VIZ", "subaccount_on_sale_fee": "1.000 VIZ", - "witness_declaration_fee": "1.000 VIZ", + "validator_declaration_fee": "1.000 VIZ", "withdraw_intervals": 28 }] }] @@ -113,7 +113,7 @@ --- -## `account_witness_vote_operation`(ID 7) +## `account_validator_vote_operation`(ID 7) **授权:** `account` 的 `active` @@ -138,7 +138,7 @@ --- -## `account_witness_proxy_operation`(ID 8) +## `account_validator_proxy_operation`(ID 8) **授权:** `account` 的 `active` diff --git a/@l10n/zh-CN/docs/protocol/virtual-operations.md b/@l10n/zh-CN/docs/protocol/virtual-operations.md index 221005aad8..843380b33d 100644 --- a/@l10n/zh-CN/docs/protocol/virtual-operations.md +++ b/@l10n/zh-CN/docs/protocol/virtual-operations.md @@ -115,7 +115,7 @@ ## 验证者操作 -### `shutdown_witness_operation`(ID 30) +### `shutdown_validator_operation`(ID 30) **触发条件:** 验证者因票权不足被停用 @@ -125,7 +125,7 @@ --- -### `witness_reward_operation`(ID 42) +### `validator_reward_operation`(ID 42) **触发条件:** 生产区块 — 验证者获得区块奖励 diff --git a/@l10n/zh-CN/docs/storage/snapshots.md b/@l10n/zh-CN/docs/storage/snapshots.md index f7292f9b26..35c5580b77 100644 --- a/@l10n/zh-CN/docs/storage/snapshots.md +++ b/@l10n/zh-CN/docs/storage/snapshots.md @@ -208,6 +208,7 @@ snapshot-dir = /data/viz-snapshots ```ini trusted-snapshot-peer = seed1.viz.world:8092 trusted-snapshot-peer = seed2.viz.world:8092 +trusted-snapshot-peer = seed3.viz.world:8092 sync-snapshot-from-trusted-peer = true ``` diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ce94bad86..a9511e4430 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -62,15 +62,7 @@ if(BUILD_TESTNET) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DBUILD_TESTNET") endif() -option(LOW_MEMORY_NODE "Build source for low memory node (ON OR OFF)" FALSE) -message(STATUS "LOW_MEMORY_NODE: ${LOW_MEMORY_NODE}") -if(LOW_MEMORY_NODE) - message(STATUS " ") - message(STATUS " CONFIGURING FOR LOW MEMORY NODE ") - message(STATUS " ") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DIS_LOW_MEM") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DIS_LOW_MEM") -endif() + option(CHAINBASE_CHECK_LOCKING "Check locks in chainbase (ON or OFF)" TRUE) message(STATUS "CHAINBASE_CHECK_LOCKING: ${CHAINBASE_CHECK_LOCKING}") @@ -255,8 +247,4 @@ else() message(STATUS "\n\n CONFIGURED FOR VIZ NETWORK \n\n") endif() -if(LOW_MEMORY_NODE) - message(STATUS "\n\n CONFIGURED FOR LOW MEMORY NODE \n\n") -else() - message(STATUS "\n\n CONFIGURED FOR FULL NODE \n\n") -endif() + diff --git a/README.md b/README.md index f60ce27293..c28f49c9ea 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ![Build docker images](https://github.com/VIZ-Blockchain/viz-cpp-node/workflows/Build%20docker%20images/badge.svg) -VIZ is a Graphene blockchain with a Fair-DPOS consensus algorithm (vote weight splitted to selected witnesses, witness gets a penalty for missing a block). +VIZ is a Graphene blockchain with a Fair-DPOS consensus algorithm (vote weight splitted to selected validators, validator gets a penalty for missing a block). ## Building diff --git a/build-linux.sh b/build-linux.sh index ce3b7bd9c0..f4731f7873 100644 --- a/build-linux.sh +++ b/build-linux.sh @@ -16,7 +16,7 @@ # # Options: # -t, --type TYPE Build type: Release or Debug (default: Release) -# -l, --lowmem Build low memory node (LOW_MEMORY_NODE=ON) + # -n, --testnet Build for testnet (BUILD_TESTNET=ON) # -m, --mongo (removed — mongo_db plugin moved to examples-plugins) # -s, --static Build shared libraries OFF (static linking) @@ -33,7 +33,7 @@ set -euo pipefail # --- Defaults --- BUILD_TYPE="Release" -LOW_MEMORY="OFF" + BUILD_TESTNET="OFF" SHARED_LIBS="OFF" CHAINBASE_LOCK="ON" @@ -69,8 +69,7 @@ while [[ $# -gt 0 ]]; do case $1 in -t|--type) BUILD_TYPE="$2"; shift 2 ;; - -l|--lowmem) - LOW_MEMORY="ON"; shift ;; + -n|--testnet) BUILD_TESTNET="ON"; shift ;; -s|--static) @@ -130,7 +129,7 @@ echo "============================================" echo " VIZ Linux Build" echo "============================================" echo " Build Type: $BUILD_TYPE" -echo " Low Memory Node: $LOW_MEMORY" + echo " Build Testnet: $BUILD_TESTNET" echo " Shared Libs: $SHARED_LIBS" echo " Chainbase Locks: $CHAINBASE_LOCK" @@ -152,7 +151,7 @@ info "[1/3] Configuring with CMake..." cmake -S "$SOURCE_DIR" -B "$BUILD_DIR" \ -DCMAKE_BUILD_TYPE="$BUILD_TYPE" \ -DBUILD_SHARED_LIBRARIES="$SHARED_LIBS" \ - -DLOW_MEMORY_NODE="$LOW_MEMORY" \ + -DBUILD_TESTNET="$BUILD_TESTNET" \ -DCHAINBASE_CHECK_LOCKING="$CHAINBASE_LOCK" \ -DBoost_NO_BOOST_CMAKE=ON \ diff --git a/build-mac.sh b/build-mac.sh index 15b5ecf007..30347caf73 100644 --- a/build-mac.sh +++ b/build-mac.sh @@ -14,7 +14,7 @@ # # Options: # -t, --type TYPE Build type: Release or Debug (default: Release) -# -l, --lowmem Build low memory node (LOW_MEMORY_NODE=ON) + # -n, --testnet Build for testnet (BUILD_TESTNET=ON) # -s, --static Build shared libraries OFF (static linking) # --no-lock-check Disable chainbase lock checking @@ -30,7 +30,7 @@ set -euo pipefail # --- Defaults --- BUILD_TYPE="Release" -LOW_MEMORY="OFF" + BUILD_TESTNET="OFF" SHARED_LIBS="ON" CHAINBASE_LOCK="ON" @@ -60,8 +60,7 @@ while [[ $# -gt 0 ]]; do case $1 in -t|--type) BUILD_TYPE="$2"; shift 2 ;; - -l|--lowmem) - LOW_MEMORY="ON"; shift ;; + -n|--testnet) BUILD_TESTNET="ON"; shift ;; -s|--static) @@ -188,7 +187,7 @@ echo "============================================" echo " VIZ macOS Build" echo "============================================" echo " Build Type: $BUILD_TYPE" -echo " Low Memory Node: $LOW_MEMORY" + echo " Build Testnet: $BUILD_TESTNET" echo " Shared Libs: $SHARED_LIBS" echo " Chainbase Locks: $CHAINBASE_LOCK" @@ -211,7 +210,7 @@ info "[1/3] Configuring with CMake..." cmake -S "$SOURCE_DIR" -B "$BUILD_DIR" \ -DCMAKE_BUILD_TYPE="$BUILD_TYPE" \ -DBUILD_SHARED_LIBRARIES="$SHARED_LIBS" \ - -DLOW_MEMORY_NODE="$LOW_MEMORY" \ + -DBUILD_TESTNET="$BUILD_TESTNET" \ -DCHAINBASE_CHECK_LOCKING="$CHAINBASE_LOCK" \ $BOOST_ROOT_ARG \ diff --git a/build-mingw.bat b/build-mingw.bat index 9310b43a81..1fde55cb9a 100644 --- a/build-mingw.bat +++ b/build-mingw.bat @@ -15,7 +15,7 @@ REM OPENSSL_ROOT_DIR - Path to OpenSSL installation (e.g. C:\OpenSSL-Win64) REM REM Optional Environment Variables: REM VIZ_BUILD_TYPE - Release or Debug (default: Release) -REM VIZ_LOW_MEMORY - ON or OFF (default: OFF) + REM VIZ_BUILD_TESTNET - ON or OFF (default: OFF) REM VIZ_FULL_STATIC - ON or OFF (default: OFF, produces static exe) REM VIZ_CMAKE_EXTRA - Additional CMake options @@ -25,7 +25,7 @@ setlocal enabledelayedexpansion REM --- Defaults --- if not defined VIZ_BUILD_TYPE set VIZ_BUILD_TYPE=Release -if not defined VIZ_LOW_MEMORY set VIZ_LOW_MEMORY=OFF + if not defined VIZ_BUILD_TESTNET set VIZ_BUILD_TESTNET=OFF if not defined VIZ_FULL_STATIC set VIZ_FULL_STATIC=OFF @@ -73,7 +73,7 @@ echo ============================================ echo VIZ Windows Build (MinGW) echo ============================================ echo Build Type: %VIZ_BUILD_TYPE% -echo Low Memory Node: %VIZ_LOW_MEMORY% + echo Build Testnet: %VIZ_BUILD_TESTNET% echo Full Static: %VIZ_FULL_STATIC% echo BOOST_ROOT: %BOOST_ROOT% @@ -93,7 +93,7 @@ cmake -S "%SOURCE_DIR%" -B "%BUILD_DIR%" ^ -DCMAKE_BUILD_TYPE=%VIZ_BUILD_TYPE% ^ -DBOOST_ROOT="%BOOST_ROOT%" ^ -DOPENSSL_ROOT_DIR="%OPENSSL_ROOT_DIR%" ^ - -DLOW_MEMORY_NODE=%VIZ_LOW_MEMORY% ^ + -DBUILD_TESTNET=%VIZ_BUILD_TESTNET% ^ -DBUILD_SHARED_LIBRARIES=OFF ^ -DFULL_STATIC_BUILD=%VIZ_FULL_STATIC% ^ diff --git a/build-msvc.bat b/build-msvc.bat index 5f00ed269c..3548f2a21e 100644 --- a/build-msvc.bat +++ b/build-msvc.bat @@ -16,7 +16,7 @@ REM REM Optional Environment Variables: REM VIZ_VS_VERSION - Visual Studio generator version (default: "Visual Studio 17 2022") REM VIZ_BUILD_TYPE - Release or Debug (default: Release) -REM VIZ_LOW_MEMORY - ON or OFF (default: OFF) + REM VIZ_BUILD_TESTNET - ON or OFF (default: OFF) REM VIZ_CMAKE_EXTRA - Additional CMake options REM =========================================================================== @@ -26,7 +26,7 @@ setlocal enabledelayedexpansion REM --- Defaults --- if not defined VIZ_VS_VERSION set VIZ_VS_VERSION=Visual Studio 17 2022 if not defined VIZ_BUILD_TYPE set VIZ_BUILD_TYPE=Release -if not defined VIZ_LOW_MEMORY set VIZ_LOW_MEMORY=OFF + if not defined VIZ_BUILD_TESTNET set VIZ_BUILD_TESTNET=OFF REM --- Validate required environment variables --- @@ -66,7 +66,7 @@ echo VIZ Windows Build (MSVC) echo ============================================ echo Generator: %VIZ_VS_VERSION% echo Build Type: %VIZ_BUILD_TYPE% -echo Low Memory Node: %VIZ_LOW_MEMORY% + echo Build Testnet: %VIZ_BUILD_TESTNET% echo BOOST_ROOT: %BOOST_ROOT% echo OPENSSL_ROOT: %OPENSSL_ROOT_DIR% @@ -85,7 +85,7 @@ cmake -S "%SOURCE_DIR%" -B "%BUILD_DIR%" ^ -DCMAKE_BUILD_TYPE=%VIZ_BUILD_TYPE% ^ -DBOOST_ROOT="%BOOST_ROOT%" ^ -DOPENSSL_ROOT_DIR="%OPENSSL_ROOT_DIR%" ^ - -DLOW_MEMORY_NODE=%VIZ_LOW_MEMORY% ^ + -DBUILD_TESTNET=%VIZ_BUILD_TESTNET% ^ -DBUILD_SHARED_LIBRARIES=OFF ^ %VIZ_CMAKE_EXTRA% diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index c4a42e519f..150f3f181d 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -2,154 +2,425 @@ import { defineConfig, type DefaultTheme } from 'vitepress'; const githubRepo = 'https://github.com/VIZ-Blockchain/viz-cpp-node'; -// Sidebar tree shared by all locales (page paths are relative to the -// per-locale srcDir; VitePress resolves them under each locale folder). -function buildSidebar(): DefaultTheme.SidebarItem[] { +// ─── Sidebar translations ─────────────────────────────────────────────────── + +interface SidebarLabels { + introduction: string; + whatIsViz: string; + architecture: string; + keyConcepts: string; + runANode: string; + gettingStarted: string; + configuration: string; + building: string; + docker: string; + validatorNode: string; + validatorGuard: string; + snapshots: string; + monitoring: string; + consensus: string; + fairDpos: string; + blockProcessing: string; + forkResolution: string; + emergencyConsensus: string; + hardforks: string; + p2pNetwork: string; + overview: string; + messages: string; + syncScenarios: string; + forwardMode: string; + statsReference: string; + plugins: string; + validator: string; + snapshot: string; + chain: string; + databaseApi: string; + webserver: string; + protocol: string; + dataTypes: string; + virtualOperations: string; + operations: string; + accounts: string; + transfersVesting: string; + validators: string; + content: string; + recovery: string; + escrow: string; + committee: string; + invites: string; + awards: string; + subscriptions: string; + accountMarket: string; + proposals: string; + storage: string; + sharedMemory: string; + blockLog: string; + snapshotsStorage: string; + governance: string; + chainProperties: string; + stakingDao: string; + committeeGov: string; + apiReference: string; + jsonRpc: string; + cliWallet: string; + clientLibraries: string; + development: string; + buildingDev: string; + testing: string; + debugging: string; + pluginDevelopment: string; + advanced: string; + security: string; + databaseSchema: string; + dltArchitecture: string; + hardforkManagement: string; +} + +const en: SidebarLabels = { + introduction: 'Introduction', + whatIsViz: 'What is VIZ Ledger?', + architecture: 'Architecture', + keyConcepts: 'Key Concepts', + runANode: 'Run a Node', + gettingStarted: 'Getting Started', + configuration: 'Configuration', + building: 'Building from Source', + docker: 'Docker', + validatorNode: 'Validator Node', + validatorGuard: 'Validator Guard', + snapshots: 'Snapshots', + monitoring: 'Monitoring', + consensus: 'Consensus', + fairDpos: 'Fair-DPOS', + blockProcessing: 'Block Processing', + forkResolution: 'Fork Resolution', + emergencyConsensus: 'Emergency Consensus', + hardforks: 'Hardforks', + p2pNetwork: 'P2P Network', + overview: 'Overview', + messages: 'Messages', + syncScenarios: 'Sync Scenarios', + forwardMode: 'Forward Mode', + statsReference: 'Stats Reference', + plugins: 'Plugins', + validator: 'Validator', + snapshot: 'Snapshot', + chain: 'Chain', + databaseApi: 'Database API', + webserver: 'Webserver', + protocol: 'Protocol', + dataTypes: 'Data Types', + virtualOperations: 'Virtual Operations', + operations: 'Operations', + accounts: 'Accounts', + transfersVesting: 'Transfers & Vesting', + validators: 'Validators', + content: 'Content', + recovery: 'Recovery', + escrow: 'Escrow', + committee: 'Committee', + invites: 'Invites', + awards: 'Awards', + subscriptions: 'Subscriptions', + accountMarket: 'Account Market', + proposals: 'Proposals', + storage: 'Storage', + sharedMemory: 'Shared Memory', + blockLog: 'Block Log', + snapshotsStorage: 'Snapshots', + governance: 'Governance', + chainProperties: 'Chain Properties', + stakingDao: 'Staking & DAO', + committeeGov: 'Committee', + apiReference: 'API Reference', + jsonRpc: 'JSON-RPC', + cliWallet: 'CLI Wallet', + clientLibraries: 'Client Libraries', + development: 'Development', + buildingDev: 'Building', + testing: 'Testing', + debugging: 'Debugging', + pluginDevelopment: 'Plugin Development', + advanced: 'Advanced', + security: 'Security', + databaseSchema: 'Database Schema', + dltArchitecture: 'DLT Architecture', + hardforkManagement: 'Hardfork Management', +}; + +const ru: SidebarLabels = { + introduction: 'Введение', + whatIsViz: 'Что такое VIZ Ledger?', + architecture: 'Архитектура', + keyConcepts: 'Ключевые понятия', + runANode: 'Запуск узла', + gettingStarted: 'Быстрый старт', + configuration: 'Конфигурация', + building: 'Сборка из исходников', + docker: 'Docker', + validatorNode: 'Узел валидатора', + validatorGuard: 'Страж валидатора', + snapshots: 'Снимки', + monitoring: 'Мониторинг', + consensus: 'Консенсус', + fairDpos: 'Fair-DPOS', + blockProcessing: 'Обработка блоков', + forkResolution: 'Разрешение форков', + emergencyConsensus: 'Экстренный консенсус', + hardforks: 'Хардфорки', + p2pNetwork: 'Сеть P2P', + overview: 'Обзор', + messages: 'Сообщения', + syncScenarios: 'Сценарии синхронизации', + forwardMode: 'Режим пересылки', + statsReference: 'Справка по статистике', + plugins: 'Плагины', + validator: 'Валидатор', + snapshot: 'Снимок', + chain: 'Chain', + databaseApi: 'Database API', + webserver: 'Вебсервер', + protocol: 'Протокол', + dataTypes: 'Типы данных', + virtualOperations: 'Виртуальные операции', + operations: 'Операции', + accounts: 'Аккаунты', + transfersVesting: 'Переводы и вестинг', + validators: 'Валидаторы', + content: 'Контент', + recovery: 'Восстановление', + escrow: 'Эскроу', + committee: 'Комитет', + invites: 'Инвайты', + awards: 'Награды', + subscriptions: 'Подписки', + accountMarket: 'Рынок аккаунтов', + proposals: 'Предложения', + storage: 'Хранилище', + sharedMemory: 'Разделяемая память', + blockLog: 'Лог блоков', + snapshotsStorage: 'Снимки', + governance: 'Управление', + chainProperties: 'Параметры цепи', + stakingDao: 'Стейкинг и DAO', + committeeGov: 'Комитет', + apiReference: 'Справочник API', + jsonRpc: 'JSON-RPC', + cliWallet: 'CLI-кошелёк', + clientLibraries: 'Клиентские библиотеки', + development: 'Разработка', + buildingDev: 'Сборка', + testing: 'Тестирование', + debugging: 'Отладка', + pluginDevelopment: 'Разработка плагинов', + advanced: 'Продвинутое', + security: 'Безопасность', + databaseSchema: 'Схема базы данных', + dltArchitecture: 'Архитектура DLT', + hardforkManagement: 'Управление хардфорками', +}; + +const zhCN: SidebarLabels = { + introduction: '简介', + whatIsViz: '什么是 VIZ Ledger?', + architecture: '架构', + keyConcepts: '核心概念', + runANode: '运行节点', + gettingStarted: '快速开始', + configuration: '配置', + building: '从源码构建', + docker: 'Docker', + validatorNode: '验证人节点', + validatorGuard: '验证人守卫', + snapshots: '快照', + monitoring: '监控', + consensus: '共识', + fairDpos: 'Fair-DPOS', + blockProcessing: '区块处理', + forkResolution: '分叉解决', + emergencyConsensus: '紧急共识', + hardforks: '硬分叉', + p2pNetwork: 'P2P 网络', + overview: '概览', + messages: '消息', + syncScenarios: '同步场景', + forwardMode: '转发模式', + statsReference: '统计参考', + plugins: '插件', + validator: '验证人', + snapshot: '快照', + chain: 'Chain', + databaseApi: 'Database API', + webserver: 'Webserver', + protocol: '协议', + dataTypes: '数据类型', + virtualOperations: '虚拟操作', + operations: '操作', + accounts: '账户', + transfersVesting: '转账与质押', + validators: '验证人', + content: '内容', + recovery: '恢复', + escrow: '托管', + committee: '委员会', + invites: '邀请', + awards: '奖励', + subscriptions: '订阅', + accountMarket: '账户市场', + proposals: '提案', + storage: '存储', + sharedMemory: '共享内存', + blockLog: '区块日志', + snapshotsStorage: '快照', + governance: '治理', + chainProperties: '链参数', + stakingDao: '质押与 DAO', + committeeGov: '委员会', + apiReference: 'API 参考', + jsonRpc: 'JSON-RPC', + cliWallet: 'CLI 钱包', + clientLibraries: '客户端库', + development: '开发', + buildingDev: '构建', + testing: '测试', + debugging: '调试', + pluginDevelopment: '插件开发', + advanced: '高级', + security: '安全', + databaseSchema: '数据库架构', + dltArchitecture: 'DLT 架构', + hardforkManagement: '硬分叉管理', +}; + +// ─── Build sidebar from labels ────────────────────────────────────────────── + +function buildSidebar(t: SidebarLabels, prefix: string): DefaultTheme.SidebarItem[] { + const p = (path: string) => `${prefix}${path}`; return [ { - text: 'Introduction', + text: t.introduction, items: [ - { text: 'What is VIZ Ledger?', link: '/introduction/what-is-viz' }, - { text: 'Architecture', link: '/introduction/architecture' }, - { text: 'Key Concepts', link: '/introduction/key-concepts' }, + { text: t.whatIsViz, link: p('/introduction/what-is-viz') }, + { text: t.architecture, link: p('/introduction/architecture') }, + { text: t.keyConcepts, link: p('/introduction/key-concepts') }, ], }, { - text: 'Run a Node', + text: t.runANode, items: [ - { text: 'Getting Started', link: '/node/getting-started' }, - { text: 'Configuration', link: '/node/configuration' }, - { text: 'Building from Source', link: '/node/building' }, - { text: 'Docker', link: '/node/docker' }, - { text: 'Validator Node', link: '/node/validator-node' }, - { text: 'Validator Guard', link: '/node/validator-guard' }, - { text: 'Snapshots', link: '/node/snapshot' }, - { text: 'Monitoring', link: '/node/monitoring' }, + { text: t.gettingStarted, link: p('/node/getting-started') }, + { text: t.configuration, link: p('/node/configuration') }, + { text: t.building, link: p('/node/building') }, + { text: t.docker, link: p('/node/docker') }, + { text: t.validatorNode, link: p('/node/validator-node') }, + { text: t.validatorGuard, link: p('/node/validator-guard') }, + { text: t.snapshots, link: p('/node/snapshot') }, + { text: t.monitoring, link: p('/node/monitoring') }, ], }, { - text: 'Consensus', + text: t.consensus, items: [ - { text: 'Fair-DPOS', link: '/consensus/fair-dpos' }, - { text: 'Block Processing', link: '/consensus/block-processing' }, - { text: 'Fork Resolution', link: '/consensus/fork-resolution' }, - { text: 'Emergency Consensus', link: '/consensus/emergency-consensus' }, - { text: 'Hardforks', link: '/consensus/hardforks' }, + { text: t.fairDpos, link: p('/consensus/fair-dpos') }, + { text: t.blockProcessing, link: p('/consensus/block-processing') }, + { text: t.forkResolution, link: p('/consensus/fork-resolution') }, + { text: t.emergencyConsensus, link: p('/consensus/emergency-consensus') }, + { text: t.hardforks, link: p('/consensus/hardforks') }, ], }, { - text: 'P2P Network', + text: t.p2pNetwork, items: [ - { text: 'Overview', link: '/p2p/overview' }, - { text: 'Messages', link: '/p2p/messages' }, - { text: 'Sync Scenarios', link: '/p2p/sync-scenarios' }, - { text: 'Forward Mode', link: '/p2p/forward-mode' }, - { text: 'Stats Reference', link: '/p2p/stats-reference' }, + { text: t.overview, link: p('/p2p/overview') }, + { text: t.messages, link: p('/p2p/messages') }, + { text: t.syncScenarios, link: p('/p2p/sync-scenarios') }, + { text: t.forwardMode, link: p('/p2p/forward-mode') }, + { text: t.statsReference, link: p('/p2p/stats-reference') }, ], }, { - text: 'Plugins', + text: t.plugins, items: [ - { text: 'Overview', link: '/plugins/overview' }, - { text: 'Validator', link: '/plugins/validator' }, - { text: 'Snapshot', link: '/plugins/snapshot' }, - { text: 'Chain', link: '/plugins/chain' }, - { text: 'Database API', link: '/plugins/database-api' }, - { text: 'Webserver', link: '/plugins/webserver' }, + { text: t.overview, link: p('/plugins/overview') }, + { text: t.validator, link: p('/plugins/validator') }, + { text: t.snapshot, link: p('/plugins/snapshot') }, + { text: t.chain, link: p('/plugins/chain') }, + { text: t.databaseApi, link: p('/plugins/database-api') }, + { text: t.webserver, link: p('/plugins/webserver') }, ], }, { - text: 'Protocol', + text: t.protocol, items: [ - { text: 'Data Types', link: '/protocol/data-types' }, - { text: 'Virtual Operations', link: '/protocol/virtual-operations' }, + { text: t.dataTypes, link: p('/protocol/data-types') }, + { text: t.virtualOperations, link: p('/protocol/virtual-operations') }, { - text: 'Operations', + text: t.operations, collapsed: false, items: [ - { text: 'Overview', link: '/protocol/operations/overview' }, - { text: 'Accounts', link: '/protocol/operations/accounts' }, - { text: 'Transfers & Vesting', link: '/protocol/operations/transfers' }, - { text: 'Validators', link: '/protocol/operations/validators' }, - { text: 'Content', link: '/protocol/operations/content' }, - { text: 'Recovery', link: '/protocol/operations/recovery' }, - { text: 'Escrow', link: '/protocol/operations/escrow' }, - { text: 'Committee', link: '/protocol/operations/committee' }, - { text: 'Invites', link: '/protocol/operations/invites' }, - { text: 'Awards', link: '/protocol/operations/awards' }, - { text: 'Subscriptions', link: '/protocol/operations/subscriptions' }, - { text: 'Account Market', link: '/protocol/operations/account-market' }, - { text: 'Proposals', link: '/protocol/operations/proposals' }, + { text: t.overview, link: p('/protocol/operations/overview') }, + { text: t.accounts, link: p('/protocol/operations/accounts') }, + { text: t.transfersVesting, link: p('/protocol/operations/transfers') }, + { text: t.validators, link: p('/protocol/operations/validators') }, + { text: t.content, link: p('/protocol/operations/content') }, + { text: t.recovery, link: p('/protocol/operations/recovery') }, + { text: t.escrow, link: p('/protocol/operations/escrow') }, + { text: t.committee, link: p('/protocol/operations/committee') }, + { text: t.invites, link: p('/protocol/operations/invites') }, + { text: t.awards, link: p('/protocol/operations/awards') }, + { text: t.subscriptions, link: p('/protocol/operations/subscriptions') }, + { text: t.accountMarket, link: p('/protocol/operations/account-market') }, + { text: t.proposals, link: p('/protocol/operations/proposals') }, ], }, ], }, { - text: 'Storage', + text: t.storage, items: [ - { text: 'Shared Memory', link: '/storage/shared-memory' }, - { text: 'Block Log', link: '/storage/block-log' }, - { text: 'Snapshots', link: '/storage/snapshots' }, + { text: t.sharedMemory, link: p('/storage/shared-memory') }, + { text: t.blockLog, link: p('/storage/block-log') }, + { text: t.snapshotsStorage, link: p('/storage/snapshots') }, ], }, { - text: 'Governance', + text: t.governance, items: [ - { text: 'Chain Properties', link: '/governance/chain-properties' }, - { text: 'Staking & DAO', link: '/governance/staking-and-dao' }, - { text: 'Committee', link: '/governance/committee' }, + { text: t.chainProperties, link: p('/governance/chain-properties') }, + { text: t.stakingDao, link: p('/governance/staking-and-dao') }, + { text: t.committeeGov, link: p('/governance/committee') }, ], }, { - text: 'API Reference', + text: t.apiReference, items: [ - { text: 'JSON-RPC', link: '/api/json-rpc' }, - { text: 'CLI Wallet', link: '/api/cli-wallet' }, - { text: 'Client Libraries', link: '/api/client-libraries' }, + { text: t.jsonRpc, link: p('/api/json-rpc') }, + { text: t.cliWallet, link: p('/api/cli-wallet') }, + { text: t.clientLibraries, link: p('/api/client-libraries') }, ], }, { - text: 'Development', + text: t.development, items: [ - { text: 'Building', link: '/development/building' }, - { text: 'Testing', link: '/development/testing' }, - { text: 'Debugging', link: '/development/debugging' }, - { text: 'Plugin Development', link: '/development/plugin-development' }, + { text: t.buildingDev, link: p('/development/building') }, + { text: t.testing, link: p('/development/testing') }, + { text: t.debugging, link: p('/development/debugging') }, + { text: t.pluginDevelopment, link: p('/development/plugin-development') }, ], }, { - text: 'Advanced', + text: t.advanced, items: [ - { text: 'Security', link: '/advanced/security' }, - { text: 'Database Schema', link: '/advanced/database-schema' }, - { text: 'DLT Architecture', link: '/advanced/dlt-architecture' }, - { text: 'Hardfork Management', link: '/advanced/hardfork-management' }, + { text: t.security, link: p('/advanced/security') }, + { text: t.databaseSchema, link: p('/advanced/database-schema') }, + { text: t.dltArchitecture, link: p('/advanced/dlt-architecture') }, + { text: t.hardforkManagement, link: p('/advanced/hardfork-management') }, ], }, ]; } -// Prefix every internal `link` in a sidebar tree with the locale prefix -// (e.g. '/ru'). External links (http/https) are left untouched. -function prefixSidebar(items: DefaultTheme.SidebarItem[], prefix: string): DefaultTheme.SidebarItem[] { - if (!prefix) return items; - const walk = (nodes: DefaultTheme.SidebarItem[]): DefaultTheme.SidebarItem[] => - nodes.map((node) => { - const next: DefaultTheme.SidebarItem = { ...node }; - if (typeof next.link === 'string' && next.link.startsWith('/')) { - next.link = prefix + next.link; - } - if (Array.isArray(next.items)) { - next.items = walk(next.items); - } - return next; - }); - return walk(items); -} - -function localizedSidebar(prefix: string): DefaultTheme.SidebarItem[] { - return prefixSidebar(buildSidebar(), prefix); -} +// ─── Nav builder ──────────────────────────────────────────────────────────── function localizedNav( prefix: string, @@ -158,15 +429,18 @@ function localizedNav( protocolLabel: string, apiLabel: string, ): DefaultTheme.NavItem[] { + const p = (path: string) => `${prefix}${path}`; return [ - { text: introLabel, link: `${prefix}/introduction/what-is-viz` }, - { text: nodeLabel, link: `${prefix}/node/getting-started` }, - { text: protocolLabel, link: `${prefix}/protocol/data-types` }, - { text: apiLabel, link: `${prefix}/api/json-rpc` }, + { text: introLabel, link: p('/introduction/what-is-viz') }, + { text: nodeLabel, link: p('/node/getting-started') }, + { text: protocolLabel, link: p('/protocol/data-types') }, + { text: apiLabel, link: p('/api/json-rpc') }, { text: 'GitHub', link: githubRepo }, ]; } +// ─── Config ───────────────────────────────────────────────────────────────── + export default defineConfig({ title: 'VIZ Ledger Documentation', description: 'Official documentation for VIZ Ledger — hybrid DLT with Fair-DPOS consensus', @@ -192,7 +466,7 @@ export default defineConfig({ lang: 'en-US', themeConfig: { nav: localizedNav('', 'Introduction', 'Run a Node', 'Protocol', 'API'), - sidebar: localizedSidebar(''), + sidebar: buildSidebar(en, ''), }, }, ru: { @@ -200,7 +474,7 @@ export default defineConfig({ lang: 'ru', themeConfig: { nav: localizedNav('/ru', 'Введение', 'Запуск узла', 'Протокол', 'API'), - sidebar: localizedSidebar('/ru'), + sidebar: buildSidebar(ru, '/ru'), }, }, 'zh-CN': { @@ -208,7 +482,7 @@ export default defineConfig({ lang: 'zh-CN', themeConfig: { nav: localizedNav('/zh-CN', '简介', '运行节点', '协议', 'API'), - sidebar: localizedSidebar('/zh-CN'), + sidebar: buildSidebar(zhCN, '/zh-CN'), }, }, }, diff --git a/docs/PLAN.md b/docs/PLAN.md index 329aac28a5..6725231e81 100644 --- a/docs/PLAN.md +++ b/docs/PLAN.md @@ -242,7 +242,7 @@ Copy EN structure to `@l10n/ru/docs/` and `@l10n/zh-CN/docs/`, translate P0+P1 p | VIZ Blockchain | **VIZ Ledger** | Public name; explain hybrid DLT on intro page | | witness | **validator** | Already renamed in codebase (branch `witness-rename`) | | blockchain | ledger / chain | Context-dependent; "chain" OK in technical contexts | -| witness_update_operation | `validator_update_operation` | Use current operation name in docs | +| validator_update_operation | `validator_update_operation` | Use current operation name in docs | --- diff --git a/docs/advanced/database-schema.md b/docs/advanced/database-schema.md index bd8fbf6149..2f117f1f9c 100644 --- a/docs/advanced/database-schema.md +++ b/docs/advanced/database-schema.md @@ -48,7 +48,7 @@ Every persistent object has a unique numeric type ID declared in `chain_object_t Accounts store balances, vesting state, delegation metrics, bandwidth, auction/sale flags, and governance participation. -**Key fields:** `name`, `balance` (VIZ), `vesting_shares`, `delegated_vesting_shares`, `received_vesting_shares`, `energy`, `next_vesting_withdrawal`, `witnesses_voted_for`, `recovery_account`. +**Key fields:** `name`, `balance` (VIZ), `vesting_shares`, `delegated_vesting_shares`, `received_vesting_shares`, `energy`, `next_vesting_withdrawal`, `validators_voted_for`, `recovery_account`. **Indexes:** @@ -94,9 +94,9 @@ Content objects represent posts and comments with voting, payout, and nesting me --- -## Validator (Witness) Objects +## Validator Objects -**`witness_object` indexes:** +**`validator_object` indexes:** | Tag | Key | |-----|-----| diff --git a/docs/advanced/dlt-architecture.md b/docs/advanced/dlt-architecture.md index 91e24e8627..36168a1d8d 100644 --- a/docs/advanced/dlt-architecture.md +++ b/docs/advanced/dlt-architecture.md @@ -124,7 +124,7 @@ This multi-tier check prevents false "different fork" disconnections in DLT mode The fork resolution subsystem tracks competing chain tips: -- **Threshold:** 42 blocks of divergence triggers `resolve_fork()` (= `CHAIN_MAX_WITNESSES × 2`, one full schedule rotation). +- **Threshold:** 42 blocks of divergence triggers `resolve_fork()` (= `CHAIN_MAX_VALIDATORS × 2`, one full schedule rotation). - **Selection:** Heaviest branch by vote weight. - **Hysteresis:** 6 consecutive blocks as winner before switching (`CONFIRMATION_BLOCKS`). - **Status:** `_fork_status` exposed via `is_on_majority_fork()` for the validator plugin to check before producing blocks. diff --git a/docs/advanced/hardfork-management.md b/docs/advanced/hardfork-management.md index 4e2ecb9068..e4fffae7ec 100644 --- a/docs/advanced/hardfork-management.md +++ b/docs/advanced/hardfork-management.md @@ -57,7 +57,7 @@ HF12 introduces automatic network recovery when block production stalls. ### Activation -If the last irreversible block (LIB) timestamp is more than `CHAIN_EMERGENCY_CONSENSUS_TIMEOUT_SEC` (1 hour) behind wall clock, emergency mode activates automatically. An emergency validator account (`CHAIN_EMERGENCY_WITNESS_ACCOUNT = "committee"`) with a known public key (`CHAIN_EMERGENCY_WITNESS_PUBLIC_KEY`) is created and inserted into the block production schedule. +If the last irreversible block (LIB) timestamp is more than `CHAIN_EMERGENCY_CONSENSUS_TIMEOUT_SEC` (1 hour) behind wall clock, emergency mode activates automatically. An emergency validator account (`CHAIN_EMERGENCY_VALIDATOR_ACCOUNT = "committee"`) with a known public key (`CHAIN_EMERGENCY_VALIDATOR_PUBLIC_KEY`) is created and inserted into the block production schedule. ### Three-state safety enforcement diff --git a/docs/api/json-rpc.md b/docs/api/json-rpc.md index 4f510877d4..0a23db480a 100644 --- a/docs/api/json-rpc.md +++ b/docs/api/json-rpc.md @@ -52,7 +52,7 @@ All VIZ node APIs use JSON-RPC 2.0 over HTTP POST or WebSocket. |-----------|--------|-------------| | `database_api` | Active | Block, account, chain state queries | | `network_broadcast_api` | Active | Transaction and block broadcast | -| `witness_api` | Active | Validator queries | +| `validator_api` | Active | Validator queries | | `account_by_key` | Active | Reverse key lookup | | `account_history` | Active | Per-account operation history | | `operation_history` | Active | Block operation queries | @@ -119,18 +119,18 @@ All VIZ node APIs use JSON-RPC 2.0 over HTTP POST or WebSocket. --- -## `witness_api` Methods +## `validator_api` Methods | Method | Description | |--------|-------------| -| `get_active_witnesses()` | Current active validator set (21 accounts) | -| `get_witness_schedule()` | Full validator schedule object | -| `get_witnesses(ids[])` | Validators by internal IDs | -| `get_witness_by_account(account)` | Validator object for an account | -| `get_witnesses_by_vote(lower_bound, limit)` | Validators ranked by vote weight | -| `get_witnesses_by_counted_vote(lower_bound, limit)` | Validators by counted votes | -| `get_witness_count()` | Total registered validators | -| `lookup_witness_accounts(lower_bound, limit)` | List validator account names | +| `get_active_validators()` | Current active validator set (21 accounts) | +| `get_validator_schedule()` | Full validator schedule object | +| `get_validators(ids[])` | Validators by internal IDs | +| `get_validator_by_account(account)` | Validator object for an account | +| `get_validators_by_vote(lower_bound, limit)` | Validators ranked by vote weight | +| `get_validators_by_counted_vote(lower_bound, limit)` | Validators by counted votes | +| `get_validator_count()` | Total registered validators | +| `lookup_validator_accounts(lower_bound, limit)` | List validator account names | --- @@ -214,7 +214,7 @@ plugin = database_api network_broadcast_api **Full API node (add):** ```ini -plugin = witness_api account_by_key account_history operation_history +plugin = validator_api account_by_key account_history operation_history plugin = committee_api invite_api paid_subscription_api ``` diff --git a/docs/consensus/block-processing.md b/docs/consensus/block-processing.md index 8e79e3e167..e1065b77f9 100644 --- a/docs/consensus/block-processing.md +++ b/docs/consensus/block-processing.md @@ -279,7 +279,7 @@ check_block_post_validation_chain(): struct block_post_validation_message { block_id_type block_id; std::string witness_account; // validator name - signature_type witness_signature; // sign(chain_id + block_id) + signature_type validator_signature; // sign(chain_id + block_id) }; ``` diff --git a/docs/consensus/emergency-consensus.md b/docs/consensus/emergency-consensus.md index 82b5a00544..74d7d0092d 100644 --- a/docs/consensus/emergency-consensus.md +++ b/docs/consensus/emergency-consensus.md @@ -9,11 +9,11 @@ Emergency consensus mode (introduced in HF12) activates automatically when the n | Constant | Value | Meaning | |----------|-------|---------| | `CHAIN_EMERGENCY_CONSENSUS_TIMEOUT_SEC` | 3600 s | Inactivity time before activation | -| `CHAIN_EMERGENCY_WITNESS_ACCOUNT` | `"committee"` | Emergency block producer account | -| `CHAIN_EMERGENCY_WITNESS_PUBLIC_KEY` | `VIZ75CR...` | Deterministic emergency signing key | +| `CHAIN_EMERGENCY_VALIDATOR_ACCOUNT` | `"committee"` | Emergency block producer account | +| `CHAIN_EMERGENCY_VALIDATOR_PUBLIC_KEY` | `VIZ75CR...` | Deterministic emergency signing key | | `CHAIN_EMERGENCY_EXIT_NORMAL_BLOCKS` | 21 | Consecutive real-validator blocks for exit | | `CHAIN_IRREVERSIBLE_THRESHOLD` | 75% | Fraction of schedule slots required to exit | -| `CHAIN_MAX_WITNESSES` | 21 | Maximum validator slots | +| `CHAIN_MAX_VALIDATORS` | 21 | Maximum validator slots | ### State fields in `dynamic_global_property_object` @@ -41,12 +41,12 @@ When the timeout threshold is crossed: 1. Set `dgp.emergency_consensus_active = true` and `dgp.emergency_consensus_start_block = block_num`. 2. Create or update the "committee" validator object: - - `signing_key = CHAIN_EMERGENCY_WITNESS_PUBLIC_KEY` + - `signing_key = CHAIN_EMERGENCY_VALIDATOR_PUBLIC_KEY` - `props = current_median_props` - Hardfork votes set to the currently applied version (neutral voter). 3. Disable ALL real validators: set `signing_key = zero`, reset `penalty_percent = 0`, `current_run = 0`. 4. Remove all `witness_penalty_expire` objects. -5. Override the validator schedule: all `CHAIN_MAX_WITNESSES` slots → "committee". +5. Override the validator schedule: all `CHAIN_MAX_VALIDATORS` slots → "committee". 6. Notify fork DB: `_fork_db.set_emergency_mode(true)` (enables deterministic hash tie-breaking). 7. Log: `"EMERGENCY CONSENSUS MODE activated at block #N. No blocks for X seconds since LIB Y."` @@ -60,7 +60,7 @@ Nodes with `emergency-private-key` configured in `config.ini` are **emergency ma ```ini # Emergency master node only -emergency-private-key = 5Jzzz... # CHAIN_EMERGENCY_WITNESS_ACCOUNT private key +emergency-private-key = 5Jzzz... # CHAIN_EMERGENCY_VALIDATOR_ACCOUNT private key ``` | Role | DLT sync check | Minority fork check | Production | @@ -105,7 +105,7 @@ Committee is excluded from hardfork version tallying and median chain property c Every schedule rebuild checks the exit condition: ``` -real_witness_slots >= CHAIN_MAX_WITNESSES × 75% +real_witness_slots >= CHAIN_MAX_VALIDATORS × 75% ``` With 21 validators: `21 × 0.75 = 15.75 → 15` real validator slots required. @@ -133,7 +133,7 @@ This ensures the schedule is always consistent after an unclean shutdown during ## Validator Guard Integration -The `witness_guard` plugin continues to operate during emergency and is in fact more critical: +The `validator_guard` plugin continues to operate during emergency and is in fact more critical: - Real validators are disabled (signing key set to null) during activation. - The validator guard automatically broadcasts `validator_update_operation` to restore each validator's signing key once the null key is detected on-chain. @@ -199,7 +199,7 @@ Snapshots created during an active emergency preserve the state correctly; snaps | 9 | `stale_sync_check_task` | Skip if master's head advancing; allow if follower stuck | | 10 | `handle_block` | Near-caught-up blocks treated as normal in DLT emergency | | 11 | `database::open` | Startup schedule repair | -| 12 | `witness_guard` | Do not suppress key restoration during emergency | +| 12 | `validator_guard` | Do not suppress key restoration during emergency | | 13 | `snapshot import` | Forward-compatible field handling | | 14 | `update_witness_schedule` | Exclude committee from hardfork version tallying | | 15 | `update_median_witness_props` | Exclude committee from median computation | diff --git a/docs/consensus/fair-dpos.md b/docs/consensus/fair-dpos.md index c7102063b6..39a1b55aba 100644 --- a/docs/consensus/fair-dpos.md +++ b/docs/consensus/fair-dpos.md @@ -116,8 +116,8 @@ The check is bypassed when: If no block has been produced for `CHAIN_EMERGENCY_CONSENSUS_TIMEOUT_SEC` (default 1 hour), the chain switches to **emergency mode**: -- All 21 validator slots are assigned to `CHAIN_EMERGENCY_WITNESS_ACCOUNT` ("committee"). -- The emergency validator signs blocks using `CHAIN_EMERGENCY_WITNESS_PUBLIC_KEY`. +- All 21 validator slots are assigned to `CHAIN_EMERGENCY_VALIDATOR_ACCOUNT` ("committee"). +- The emergency validator signs blocks using `CHAIN_EMERGENCY_VALIDATOR_PUBLIC_KEY`. - All validator penalties are reset; shut-down validators are re-enabled. - LIB advancement is paused during the emergency period. - Emergency mode exits after `CHAIN_EMERGENCY_EXIT_NORMAL_BLOCKS` (21) consecutive normal blocks advance LIB past the emergency start block. @@ -146,7 +146,7 @@ See [Fork Resolution](./fork-resolution.md) for the full fork collision algorith | `required-participation` | `33` (33%) | Minimum participation to produce blocks | | `enable-stale-production` | `false` | Bypass participation check (testnet only) | | `emergency-private-key` | — | Optional emergency consensus signing key | -| Active validators | 21 | Hardcoded in `CHAIN_MAX_WITNESSES` | +| Active validators | 21 | Hardcoded in `CHAIN_MAX_VALIDATORS` | | Block interval | 3 s | `CHAIN_BLOCK_INTERVAL` | | LIB threshold | ⌈21 × 2/3⌉ = 14 | Blocks confirming irreversibility | | Emergency timeout | 3600 s | `CHAIN_EMERGENCY_CONSENSUS_TIMEOUT_SEC` | diff --git a/docs/consensus/hardforks.md b/docs/consensus/hardforks.md index c03097432c..e56d7c35f3 100644 --- a/docs/consensus/hardforks.md +++ b/docs/consensus/hardforks.md @@ -44,7 +44,7 @@ HF13 (version 3.2.0) introduced: **Validator reward sharing**: part of each block's validator reward is redistributed proportionally to the accounts that voted for that validator (by their SHARES vote weight). -- New field on `witness_object`: `reward_percent` — fraction of block reward shared with voters (0–10000 basis points). +- New field on `validator_object`: `reward_percent` — fraction of block reward shared with voters (0–10000 basis points). - New virtual operation: `validator_reward_virtual_operation` — fired once per reward distribution. - Set via `validator_update_operation`. @@ -121,7 +121,7 @@ case CHAIN_HARDFORK_N: { | Plugin | What to update | |--------|----------------| | `account_history` | Add impact extractor for any new virtual operation | -| `witness_api` | Add new fields from `witness_object` to `witness_api_object` | +| `validator_api` | Add new fields from `validator_object` to `validator_api_object` | | `snapshot` | Add new chainbase objects to `serialize_state` / `load_snapshot` | --- @@ -163,7 +163,7 @@ Normal restart: - [ ] All new fields have zero defaults; `apply_hardfork` comment explains why no migration needed - [ ] New evaluator registered in `initialize_evaluators()` - [ ] New virtual op registered in `account_history` plugin -- [ ] `witness_api_object` updated if `witness_object` changed +- [ ] `validator_api_object` updated if `validator_object` changed - [ ] Snapshot plugin updated if new chainbase objects added --- diff --git a/docs/development/building.md b/docs/development/building.md index e80942e589..f25d27de5f 100644 --- a/docs/development/building.md +++ b/docs/development/building.md @@ -113,9 +113,7 @@ The repository ships Dockerfiles for multiple configurations: | Dockerfile | Description | |-----------|-------------| -| `Dockerfile-production` | Full node, Release, no MongoDB | -| `Dockerfile-lowmem` | Same but with `LOW_MEMORY_NODE=ON` | -| `Dockerfile-mongo` | MongoDB plugin enabled | +| `Dockerfile-production` | Full mainnet node (Release) | | `Dockerfile-testnet` | Testnet (`BUILD_TESTNET=ON`) | All Dockerfiles use a two-stage build to minimize image size and use Boost 1.71 packages (`libboost-coroutine-dev`, `libboost-context-dev`). @@ -129,7 +127,6 @@ All Dockerfiles use a two-stage build to minimize image size and use Boost 1.71 | `BUILD_TESTNET` | OFF | Build for testnet | | `LOW_MEMORY_NODE` | OFF | Exclude non-consensus data (reduces RAM) | | `CHAINBASE_CHECK_LOCKING` | OFF | Enable lock checking (development only) | -| `ENABLE_MONGO_PLUGIN` | OFF | Include MongoDB plugin | | `BUILD_SHARED_LIBRARIES` | OFF | Build shared libraries | | `USE_PCH` | OFF | Enable precompiled headers (faster rebuilds) | diff --git a/docs/development/testing.md b/docs/development/testing.md index 99e741161b..178f1f5480 100644 --- a/docs/development/testing.md +++ b/docs/development/testing.md @@ -128,8 +128,6 @@ The CI matrix builds Docker images for multiple variants: | Variant | Dockerfile | |---------|-----------| | Standard | `Dockerfile-production` | -| Low-memory | `Dockerfile-lowmem` | -| MongoDB | `Dockerfile-mongo` | | Testnet | `Dockerfile-testnet` | Builds trigger per branch and tag, with artifact publishing when credentials are configured. diff --git a/docs/governance/chain-properties.md b/docs/governance/chain-properties.md index 6549b119b7..52ae9beb4e 100644 --- a/docs/governance/chain-properties.md +++ b/docs/governance/chain-properties.md @@ -41,7 +41,7 @@ The median resists extremes: a single validator cannot cause a sudden large shif ### 3. Application -The resulting `median_props` object is stored in the `witness_schedule_object` and enforced across all block processing. +The resulting `median_props` object is stored in the `validator_schedule_object` and enforced across all block processing. --- @@ -69,11 +69,11 @@ The resulting `median_props` object is stored in the `witness_schedule_object` a | Property | Type | Default | Description | |----------|------|---------|-------------| -| `inflation_witness_percent` | uint16 (bp) | 2000 (20%) | Validator share of block inflation | +| `inflation_validator_percent` | uint16 (bp) | 2000 (20%) | Validator share of block inflation | | `inflation_ratio_committee_vs_reward_fund` | uint16 (bp) | 5000 (50%) | Split of remaining inflation: committee fund vs reward fund | | `inflation_recalc_period` | uint32 (blocks) | 806400 (~28d) | How often inflation is recalculated | -Inflation flow: `block_reward × inflation_witness_percent` → validator. Remainder split: `inflation_ratio_committee_vs_reward_fund` → committee fund; the rest → award reward fund. +Inflation flow: `block_reward × inflation_validator_percent` → validator. Remainder split: `inflation_ratio_committee_vs_reward_fund` → committee fund; the rest → award reward fund. ### Reward System @@ -88,8 +88,8 @@ Inflation flow: `block_reward × inflation_witness_percent` → validator. Remai | Property | Type | Default | Description | |----------|------|---------|-------------| -| `witness_miss_penalty_percent` | uint16 (bp) | 100 (1%) | Vote weight reduction on missed block | -| `witness_miss_penalty_duration` | uint32 (s) | 86400 (1d) | How long the miss penalty lasts | +| `validator_miss_penalty_percent` | uint16 (bp) | 100 (1%) | Vote weight reduction on missed block | +| `validator_miss_penalty_duration` | uint32 (s) | 86400 (1d) | How long the miss penalty lasts | ### Fees @@ -101,7 +101,7 @@ All fees go to the committee fund (DAO treasury). | `create_paid_subscription_fee` | asset (VIZ) | 100.000 VIZ | Fee to create a paid subscription | | `account_on_sale_fee` | asset (VIZ) | 10.000 VIZ | Fee to list an account for sale | | `subaccount_on_sale_fee` | asset (VIZ) | 100.000 VIZ | Fee to list subaccount creation rights for sale | -| `witness_declaration_fee` | asset (VIZ) | 10.000 VIZ | One-time fee for validator registration | +| `validator_declaration_fee` | asset (VIZ) | 10.000 VIZ | One-time fee for validator registration | | `create_invite_min_balance` | asset (VIZ) | 10.000 VIZ | Minimum invite balance | ### Vesting Withdrawal @@ -119,9 +119,9 @@ Properties were introduced in hardfork stages: | Version | Index | Hardfork | Fields added | |---------|-------|----------|--------------| | `chain_properties_init` | 0 | Genesis | account_creation_fee, maximum_block_size, delegation params, curation, bandwidth, flag cost, vote min rshares, committee threshold | -| `chain_properties_hf4` | 1 | HF4 | inflation_witness_percent, inflation_ratio_committee_vs_reward_fund, inflation_recalc_period | -| `chain_properties_hf6` | 2 | HF6 | data_operations_cost_additional_bandwidth, witness_miss_penalty_percent, witness_miss_penalty_duration | -| `chain_properties_hf9` | 3 | HF9 | create_invite_min_balance, committee_create_request_fee, create_paid_subscription_fee, account_on_sale_fee, subaccount_on_sale_fee, witness_declaration_fee, withdraw_intervals | +| `chain_properties_hf4` | 1 | HF4 | inflation_validator_percent, inflation_ratio_committee_vs_reward_fund, inflation_recalc_period | +| `chain_properties_hf6` | 2 | HF6 | data_operations_cost_additional_bandwidth, validator_miss_penalty_percent, validator_miss_penalty_duration | +| `chain_properties_hf9` | 3 | HF9 | create_invite_min_balance, committee_create_request_fee, create_paid_subscription_fee, account_on_sale_fee, subaccount_on_sale_fee, validator_declaration_fee, withdraw_intervals | Use version index 3 (`chain_properties_hf9`) for all new validator property submissions. diff --git a/docs/governance/staking-and-dao.md b/docs/governance/staking-and-dao.md index f10c15f3b7..5758f83b43 100644 --- a/docs/governance/staking-and-dao.md +++ b/docs/governance/staking-and-dao.md @@ -75,10 +75,10 @@ SHARES are the universal governance token. Every meaningful action is weighted b Vote weight is **divided equally** among all validators the account votes for: ``` -fair_weight = effective_vesting_shares / witnesses_voted_for +fair_weight = effective_vesting_shares / validators_voted_for ``` -This prevents concentration — voting for 10 validators gives each 1/10 of your weight. Accounts may also set a proxy (`account_witness_proxy_operation`) to delegate all validator voting to another account. +This prevents concentration — voting for 10 validators gives each 1/10 of your weight. Accounts may also set a proxy (`account_validator_proxy_operation`) to delegate all validator voting to another account. ### 2. Committee DAO Voting @@ -159,7 +159,7 @@ Stake VIZ → Get SHARES → Governance Power | `CHAIN_MAX_WITHDRAW_ROUTES` | 10 | Max withdrawal routes per account | | `CHAIN_ENERGY_REGENERATION_SECONDS` | 432000 (5d) | Full energy regeneration | | `CHAIN_100_PERCENT` | 10000 | Basis points denominator | -| `CHAIN_MAX_ACCOUNT_WITNESS_VOTES` | 100 | Max validators per account | +| `CHAIN_MAX_ACCOUNT_VALIDATOR_VOTES` | 100 | Max validators per account | --- diff --git a/docs/introduction/architecture.md b/docs/introduction/architecture.md index c269787e22..4aa57937af 100644 --- a/docs/introduction/architecture.md +++ b/docs/introduction/architecture.md @@ -57,7 +57,7 @@ Plugins are registered with the `AppBase` framework at startup and implement lif | `account_by_key` | Lookup accounts by public key | | `follow` | Follow/ignore relationship index | | `tags` | Tag-based content indexing | -| `witness_api` | Validator schedule and signing key queries | +| `validator_api` | Validator schedule and signing key queries | | `debug_node` | Test utilities: inject blocks, set time | --- diff --git a/docs/introduction/key-concepts.md b/docs/introduction/key-concepts.md index bc551a49cc..3dd3154150 100644 --- a/docs/introduction/key-concepts.md +++ b/docs/introduction/key-concepts.md @@ -76,7 +76,7 @@ When an account performs an award with `energy = 500` (5%), that fraction of the Unlike standard DPOS, VIZ Ledger penalizes inactivity: - Each validator has a **participation score** based on recent block production. - If network-wide participation drops below `required-participation` (default 33%), block production pauses. -- Validators that miss too many blocks receive a vote penalty applied for `witness_miss_penalty_duration` seconds. +- Validators that miss too many blocks receive a vote penalty applied for `validator_miss_penalty_duration` seconds. --- @@ -89,7 +89,7 @@ A signed bundle of transactions produced by a validator at its scheduled slot. C - `timestamp`: the exact slot time - `witness`: name of the producing validator - `transactions[]`: list of signed transactions -- `witness_signature`: validator's signature +- `validator_signature`: validator's signature ### Transaction @@ -112,7 +112,7 @@ Inflation is continuously added to the reward pool. Validators and content creat | Recipient | Source | |-----------|--------| -| Validators | `inflation_witness_percent` of block reward | +| Validators | `inflation_validator_percent` of block reward | | Committee | `inflation_ratio_committee_vs_reward_fund` fraction | | Reward fund | Remainder — distributed via awards and content votes | @@ -146,8 +146,8 @@ On-chain consensus parameters are controlled by validators via `versioned_chain_ Key parameters include: - `account_creation_fee` — cost to create a new account - `maximum_block_size` — max bytes per block -- `inflation_witness_percent` — validator share of block reward -- `witness_miss_penalty_percent` / `witness_miss_penalty_duration` — miss penalty +- `inflation_validator_percent` — validator share of block reward +- `validator_miss_penalty_percent` / `validator_miss_penalty_duration` — miss penalty - `withdraw_intervals` — number of vesting withdrawal intervals See [Chain Properties Governance](../governance/chain-properties.md) for the full parameter list. diff --git a/docs/node/building.md b/docs/node/building.md index 532daaba9c..682aff4ed2 100644 --- a/docs/node/building.md +++ b/docs/node/building.md @@ -126,7 +126,6 @@ For direct CMake usage (advanced): | `BUILD_TESTNET` | `OFF` | Enable testnet-specific code | | `LOW_MEMORY_NODE` | `OFF` | Exclude history/indexing plugins | | `CHAINBASE_CHECK_LOCKING` | `OFF` | Enable lock assertion checks (debug) | -| `ENABLE_MONGO_PLUGIN` | `OFF` | Build MongoDB plugin | | `BUILD_SHARED_LIBRARIES` | `OFF` | Build shared libraries | | `USE_PCH` | `OFF` | Enable precompiled headers (faster rebuilds) | @@ -165,8 +164,6 @@ The repository ships four Dockerfiles: | File | Purpose | |------|---------| | `Dockerfile-production` | Full mainnet node (Release) | -| `Dockerfile-lowmem` | Low-memory node (`LOW_MEMORY_NODE=ON`) | -| `Dockerfile-mongo` | Node with MongoDB plugin | | `Dockerfile-testnet` | Testnet node (`BUILD_TESTNET=ON`) | Build example: diff --git a/docs/node/configuration.md b/docs/node/configuration.md index 412dfcf33a..cb24707188 100644 --- a/docs/node/configuration.md +++ b/docs/node/configuration.md @@ -7,8 +7,6 @@ VIZ Ledger nodes are configured via an INI file. The repository ships several te | `config.ini` | Full mainnet node with public RPC | | `config_witness.ini` | Validator node (localhost RPC, block production) | | `config_testnet.ini` | Testnet / development | -| `config_mongo.ini` | Node with MongoDB history backend | -| `config_lowmem.ini` | Low-memory consensus/seed node | | `config_stock_exchange.ini` | Market data consumer (minimal plugins) | | `config_debug.ini` | Debug mode | @@ -26,6 +24,7 @@ p2p-max-connections = 200 # Seed nodes to bootstrap connectivity (repeatable) p2p-seed-node = seed1.viz.world:2001 p2p-seed-node = seed2.viz.world:2001 +p2p-seed-node = seed3.viz.world:2001 # Checkpoints: trusted (block_num, block_id) pairs (repeatable) # checkpoint = [12345,"0003039..." ] @@ -112,7 +111,7 @@ plugin = social_network tags follow account_history account_by_key plugin = committee_api invite_api paid_subscription_api custom_protocol_api # For validator nodes only: -plugin = validator witness_api +plugin = validator validator_api ``` ### Plugin sets by node type @@ -120,7 +119,7 @@ plugin = validator witness_api | Node type | Plugins | |-----------|---------| | Full node | All above | -| Validator | `chain p2p webserver json_rpc database_api network_broadcast_api validator witness_api` | +| Validator | `chain p2p webserver json_rpc database_api network_broadcast_api validator validator_api` | | Low-memory seed | `chain p2p` | | Stock exchange | `chain p2p webserver json_rpc database_api network_broadcast_api account_history` | @@ -198,17 +197,6 @@ logger.p2p.appenders = p2p --- -## MongoDB (Optional) - -Only relevant when the node is built with `ENABLE_MONGO_PLUGIN=ON`: - -```ini -plugin = mongo_db -mongodb-uri = mongodb://localhost:27017/vizd -``` - ---- - ## Complete Reference All options listed by source file: diff --git a/docs/node/docker.md b/docs/node/docker.md index 1ef3bcfce7..105f76a214 100644 --- a/docs/node/docker.md +++ b/docs/node/docker.md @@ -1,6 +1,6 @@ # Docker Deployment -VIZ Ledger ships four Docker images for different deployment profiles. All use a two-stage build: the builder stage compiles the binary; the runtime stage contains only the binary and configuration. +VIZ Ledger ships Docker images for different deployment profiles. All use a two-stage build: the builder stage compiles the binary; the runtime stage contains only the binary and configuration. --- @@ -9,8 +9,6 @@ VIZ Ledger ships four Docker images for different deployment profiles. All use a | Dockerfile | Tag | Description | |-----------|-----|-------------| | `Dockerfile-production` | `latest` | Full mainnet node (Release, all plugins) | -| `Dockerfile-lowmem` | `lowmem` | Low-memory node (`LOW_MEMORY_NODE=ON`, no history indexes) | -| `Dockerfile-mongo` | `mongo` | Full node with MongoDB history plugin | | `Dockerfile-testnet` | `testnet` | Testnet node (`BUILD_TESTNET=ON`) | --- @@ -62,7 +60,7 @@ The entry script (`vizd.sh`) reads these environment variables: | Variable | Description | Example | |----------|-------------|---------| -| `VIZD_SEED_NODES` | Space-delimited seed node list (overrides `/etc/vizd/seednodes`) | `seed1.viz.world:2001 seed2.viz.world:2001` | +| `VIZD_SEED_NODES` | Space-delimited seed node list (overrides `/etc/vizd/seednodes`) | `seed1.viz.world:2001 seed2.viz.world:2001 seed3.viz.world:2001` | | `VIZD_RPC_ENDPOINT` | Override HTTP RPC endpoint | `0.0.0.0:8090` | | `VIZD_P2P_ENDPOINT` | Override P2P endpoint | `0.0.0.0:2001` | | `VIZD_WITNESS` | Validator account name (enables block production) | `alice` | @@ -123,21 +121,19 @@ docker build \ -t vizd:local \ . -# Low-memory +# Testnet docker build \ - -f share/vizd/docker/Dockerfile-lowmem \ - -t vizd:lowmem \ + -f share/vizd/docker/Dockerfile-testnet \ + -t vizd:testnet \ . ``` ### CMake flags per image -| Image | `LOW_MEMORY_NODE` | `ENABLE_MONGO_PLUGIN` | `BUILD_TESTNET` | -|-------|:-----------------:|:---------------------:|:---------------:| -| production | OFF | OFF | OFF | -| lowmem | ON | OFF | OFF | -| mongo | OFF | ON | OFF | -| testnet | OFF | OFF | ON | +| Image | `LOW_MEMORY_NODE` | `BUILD_TESTNET` | +|-------|:-----------------:|:---------------:| +| production | OFF | OFF | +| testnet | OFF | ON | --- @@ -161,7 +157,7 @@ The repository ships `.github/workflows/docker-main.yml` which builds and pushes | Node type | RAM | Disk | |-----------|-----|------| | Full node (mainnet) | 8 GB+ | 50 GB+ | -| Low-memory / validator | 4 GB | 20 GB | +| Validator node | 4 GB | 20 GB | | Testnet | 4 GB | 10 GB | Start with a shared memory size that fits comfortably in RAM. In `config.ini`: diff --git a/docs/node/getting-started.md b/docs/node/getting-started.md index 8f13e818df..66b341143a 100644 --- a/docs/node/getting-started.md +++ b/docs/node/getting-started.md @@ -122,6 +122,7 @@ Minimum edits for a public node: p2p-endpoint = 0.0.0.0:2001 p2p-seed-node = seed1.viz.world:2001 p2p-seed-node = seed2.viz.world:2001 +p2p-seed-node = seed3.viz.world:2001 # RPC webserver-http-endpoint = 0.0.0.0:8090 @@ -172,7 +173,6 @@ Check `head_block_number` — it should increase every 3 seconds once synced. | Validator | `config_witness.ini` | Block production, RPC on localhost only | | Testnet | `config_testnet.ini` | Development and testing | | Low-memory | `config.ini` + `LOW_MEMORY_NODE` build flag | Consensus only, no history indexes | -| MongoDB | `config_mongo.ini` | Full history in MongoDB | --- diff --git a/docs/node/snapshot.md b/docs/node/snapshot.md index 9ea6fbed6e..ccb99ed9c0 100644 --- a/docs/node/snapshot.md +++ b/docs/node/snapshot.md @@ -288,6 +288,7 @@ snapshot-dir = /data/viz-snapshots plugin = snapshot trusted-snapshot-peer = seed1.viz.world:8092 trusted-snapshot-peer = seed2.viz.world:8092 +trusted-snapshot-peer = seed3.viz.world:8092 sync-snapshot-from-trusted-peer = true ``` diff --git a/docs/node/validator-guard.md b/docs/node/validator-guard.md index d053f212ed..cb4ace721e 100644 --- a/docs/node/validator-guard.md +++ b/docs/node/validator-guard.md @@ -1,6 +1,6 @@ # Validator Guard -The `witness_guard` plugin automates signing-key restoration for validator accounts. When a validator's signing key is reset to null (disabling block production), the plugin detects the change and broadcasts a `witness_update_operation` to restore the key — without manual intervention. +The `validator_guard` plugin automates signing-key restoration for validator accounts. When a validator's signing key is reset to null (disabling block production), the plugin detects the change and broadcasts a `validator_update_operation` to restore the key — without manual intervention. --- @@ -15,7 +15,7 @@ The `witness_guard` plugin automates signing-key restoration for validator accou ## Enabling the Plugin ```ini -plugin = witness_guard +plugin = validator_guard ``` --- @@ -34,7 +34,7 @@ The plugin also reads `enable-stale-production` from the validator plugin config ### Example ```ini -plugin = witness_guard +plugin = validator_guard # Monitor one validator validator-guard-validator = ["alice", "5K_SIGNING_WIF", "5K_ACTIVE_WIF"] @@ -63,7 +63,7 @@ validator-guard-interval = 10 On every block: -1. **Consecutive-block auto-disable**: If a monitored validator produced `validator-guard-disable` consecutive blocks, a `witness_update_operation` with a null key is broadcast to disable it, and the validator is flagged as auto-disabled. Any block by a *different* validator resets all consecutive counters. +1. **Consecutive-block auto-disable**: If a monitored validator produced `validator-guard-disable` consecutive blocks, a `validator_update_operation` with a null key is broadcast to disable it, and the validator is flagged as auto-disabled. Any block by a *different* validator resets all consecutive counters. 2. **Transaction confirmation**: Scans for pending restore transaction IDs in the block. On match, marks the restore confirmed and clears tracking state. 3. **Look-ahead scheduling**: If any monitored validator is scheduled within the next 3 slots, triggers an immediate check so the key can be restored before the slot arrives. 4. **Periodic check**: Otherwise runs the core check every `validator-guard-interval` blocks. While the node is still catching up after startup, checks run every 10 blocks. @@ -83,7 +83,7 @@ Each check (in order): ### Restore Transaction -1. Builds a `witness_update_operation` preserving the current on-chain URL and setting the signing key to the configured public key. +1. Builds a `validator_update_operation` preserving the current on-chain URL and setting the signing key to the configured public key. 2. Wraps in a `signed_transaction` with 30-second expiration and current head block reference. 3. Signs with the configured active private key. 4. Broadcasts via P2P. @@ -113,12 +113,12 @@ Each check (in order): | `enable-stale-production detected — auto-restore is DISABLED` | Stale production mode active; restore suppressed | | `network is healthy (XX%), auto-clearing stale production override` | Stale guard lifted | | `'alice' has null signing key on-chain — initiating restore` | Null key detected, about to broadcast | -| `broadcasting witness_update [ID: ...] for 'alice' — restoring key to VIZ...` | Restore transaction sent | +| `broadcasting validator_update [ID: ...] for 'alice' — restoring key to VIZ...` | Restore transaction sent | | `CONFIRMED restoration for 'alice' in block #N` | Restore confirmed on-chain | | `POTENTIAL LONG FORK DETECTED! LIB #N is Xs old. Skipping restoration.` | Restoration skipped due to stale LIB | | `validator 'alice' produced N consecutive blocks — auto-disabling` | Consecutive-block threshold reached | | `'alice' was auto-disabled (consecutive block limit), skipping auto-restore` | Auto-restore suppressed after auto-disable | -| `witness_update FAILED for 'alice': [error]` | Broadcast failed | +| `validator_update FAILED for 'alice': [error]` | Broadcast failed | --- diff --git a/docs/node/validator-node.md b/docs/node/validator-node.md index 614bee1a79..e5f810ad4b 100644 --- a/docs/node/validator-node.md +++ b/docs/node/validator-node.md @@ -28,7 +28,7 @@ webserver-http-endpoint = 127.0.0.1:8090 webserver-ws-endpoint = 127.0.0.1:8091 # Required plugins for a validator -plugin = chain p2p webserver json_rpc database_api network_broadcast_api validator witness_api +plugin = chain p2p webserver json_rpc database_api network_broadcast_api validator validator_api # Skip virtual-op indexing to save memory (validators don't need it) skip-virtual-ops = true @@ -88,11 +88,9 @@ docker run -d \ -v /data/vizd:/var/lib/vizd \ -e VIZD_WITNESS=myvalidator \ -e VIZD_PRIVATE_KEY=5Jxxx... \ - vizblockchain/vizd:lowmem + vizblockchain/vizd:latest ``` -Use the `lowmem` image for validators — it excludes unnecessary indexing plugins. - --- ## Registering / Updating Your Validator @@ -219,7 +217,7 @@ For nodes involved in emergency consensus recovery: emergency-private-key = 5Jzzz... # Committee emergency key ``` -When set, the node automatically adds `CHAIN_EMERGENCY_WITNESS_ACCOUNT` to its validator set and participates in emergency block production. See [Emergency Consensus](../consensus/emergency-consensus.md). +When set, the node automatically adds `CHAIN_EMERGENCY_VALIDATOR_ACCOUNT` to its validator set and participates in emergency block production. See [Emergency Consensus](../consensus/emergency-consensus.md). --- diff --git a/docs/p2p/overview.md b/docs/p2p/overview.md index 6e849c2437..884fdf848c 100644 --- a/docs/p2p/overview.md +++ b/docs/p2p/overview.md @@ -172,7 +172,7 @@ The DLT P2P layer maintains its own mempool separate from the chain's `_pending_ ## Fork Resolution -The DLT P2P layer tracks fork state with a **42-block threshold** (2 full validator rounds = `CHAIN_MAX_WITNESSES × 2`). +The DLT P2P layer tracks fork state with a **42-block threshold** (2 full validator rounds = `CHAIN_MAX_VALIDATORS × 2`). `track_fork_state()` is called after each block application. When a competing fork is detected and sustained for ≥ 42 blocks, `resolve_fork()` computes the **heaviest branch** by total vote weight. A candidate branch must accumulate **6 consecutive confirmation blocks** (`dlt_fork_resolution_state::CONFIRMATION_BLOCKS`) before the node switches to it (hysteresis). diff --git a/docs/p2p/stats-reference.md b/docs/p2p/stats-reference.md index 35b119ebdc..90a0fe0147 100644 --- a/docs/p2p/stats-reference.md +++ b/docs/p2p/stats-reference.md @@ -226,7 +226,7 @@ After expiry the entry reverts to DISCONNECTED and normal backoff reconnection r | `FORWARD_STAGNATION_SEC` | 30 | Head-not-advancing threshold in FORWARD mode | | `FORWARD_BEHIND_GRACE_SEC` | 15 | Grace period after SYNC→FORWARD before `check_forward_behind()` acts | | `SYNC_STAGNATION_SEC` | 30 | No-block-received threshold in SYNC mode | -| `FORK_RESOLUTION_BLOCK_THRESHOLD` | 42 | Blocks before fork resolution triggers (2 × CHAIN_MAX_WITNESSES) | +| `FORK_RESOLUTION_BLOCK_THRESHOLD` | 42 | Blocks before fork resolution triggers (2 × CHAIN_MAX_VALIDATORS) | | `FORK_RESOLUTION_CONFIRMATION_BLOCKS` | 6 | Consecutive blocks to confirm fork resolution | --- diff --git a/docs/plugins/database-api.md b/docs/plugins/database-api.md index 200cbfd68f..11ff9689de 100644 --- a/docs/plugins/database-api.md +++ b/docs/plugins/database-api.md @@ -95,7 +95,7 @@ Returns live chain state: current head block number and ID, time, head validator { "method": "database_api.get_dynamic_global_properties", "params": [] } ``` -Key fields: `head_block_number`, `head_block_id`, `time`, `current_witness`, `total_vesting_shares`, `total_vesting_fund_viz`, `committee_fund`, `last_irreversible_block_num`, `participation_count`. +Key fields: `head_block_number`, `head_block_id`, `time`, `current_validator`, `total_vesting_shares`, `total_vesting_fund_viz`, `committee_fund`, `last_irreversible_block_num`, `participation_count`. --- @@ -405,4 +405,4 @@ Returns account namespace registrations available for sale (subaccount creation --- -See also: [Plugin Overview](./overview.md), [witness_api methods](./overview.md#witness_api), [JSON-RPC API](../api/json-rpc.md). +See also: [Plugin Overview](./overview.md), [validator_api methods](./overview.md#validator_api), [JSON-RPC API](../api/json-rpc.md). diff --git a/docs/plugins/overview.md b/docs/plugins/overview.md index 5de2a3e49b..a908163948 100644 --- a/docs/plugins/overview.md +++ b/docs/plugins/overview.md @@ -13,7 +13,6 @@ VIZ Ledger uses the **AppBase** plugin framework. Each plugin has a lifecycle (` | **API** | Expose JSON-RPC endpoints for clients | | **Index** | Index chain data into chainbase for fast queries | | **Producer** | Block signing and production | -| **External** | Integration with external systems (MongoDB) | | **Debug/Test** | Development only; not for production | --- @@ -34,7 +33,7 @@ VIZ Ledger uses the **AppBase** plugin framework. Each plugin has a lifecycle (` | `webserver` | Required for API | `json_rpc` | — | | `p2p` | Required for network | `chain` | — | | `snapshot` | Recommended | `chain` | — | -| `witness_guard` | Recommended for validators | `chain`, `p2p` | — | +| `validator_guard` | Recommended for validators | `chain`, `p2p` | — | ### API @@ -42,7 +41,7 @@ VIZ Ledger uses the **AppBase** plugin framework. Each plugin has a lifecycle (` |--------|--------|------|---------| | `database_api` | Active | `json_rpc`, `chain` | Yes | | `network_broadcast_api` | Active | `json_rpc`, `chain`, `p2p` | Yes | -| `witness_api` | Active | `json_rpc`, `chain` | Yes | +| `validator_api` | Active | `json_rpc`, `chain` | Yes | | `account_by_key` | Active | `json_rpc`, `chain` | Yes | | `account_history` | Active | `json_rpc`, `chain`, `operation_history` | Yes | | `operation_history` | Active | `json_rpc`, `chain` | Yes | @@ -64,12 +63,6 @@ VIZ Ledger uses the **AppBase** plugin framework. Each plugin has a lifecycle (` |--------|--------|------|---------| | `validator` | Active | `chain`, `p2p` | — | -### External - -| Plugin | Status | Deps | JSON-RPC | -|--------|--------|------|---------| -| `mongo_db` | Active | `chain` | — | - ### Debug / Test | Plugin | Status | Deps | JSON-RPC | @@ -196,20 +189,20 @@ Submit and broadcast signed transactions and blocks. --- -### `witness_api` +### `validator_api` Query validator state: active set, schedule, individual validators, vote rankings. | Method | Description | |--------|-------------| -| `get_active_witnesses` | Current 21-validator active set | -| `get_witness_schedule` | Full schedule object | -| `get_witnesses` | Validators by database IDs | -| `get_witness_by_account` | Single validator by account name | -| `get_witnesses_by_vote` | Validators sorted by total vote weight | -| `get_witnesses_by_counted_vote` | Validators sorted by counted vote weight | -| `get_witness_count` | Total number of registered validators | -| `lookup_witness_accounts` | List validator account names by prefix | +| `get_active_validators` | Current 21-validator active set | +| `get_validator_schedule` | Full schedule object | +| `get_validators` | Validators by database IDs | +| `get_validator_by_account` | Single validator by account name | +| `get_validators_by_vote` | Validators sorted by total vote weight | +| `get_validators_by_counted_vote` | Validators sorted by counted vote weight | +| `get_validator_count` | Total number of registered validators | +| `lookup_validator_accounts` | List validator account names by prefix | --- @@ -347,7 +340,7 @@ plugin = webserver plugin = p2p plugin = database_api plugin = network_broadcast_api -plugin = witness_api +plugin = validator_api plugin = account_by_key plugin = account_history plugin = operation_history @@ -366,7 +359,7 @@ plugin = json_rpc plugin = webserver plugin = database_api plugin = network_broadcast_api -plugin = witness_api +plugin = validator_api plugin = snapshot snapshot-every-n-blocks = 28800 diff --git a/docs/plugins/snapshot.md b/docs/plugins/snapshot.md index 0fb52ab162..dce442ccdb 100644 --- a/docs/plugins/snapshot.md +++ b/docs/plugins/snapshot.md @@ -286,6 +286,7 @@ snapshot-dir = /data/snapshots plugin = snapshot trusted-snapshot-peer = seed1.viz.world:8092 trusted-snapshot-peer = seed2.viz.world:8092 +trusted-snapshot-peer = seed3.viz.world:8092 sync-snapshot-from-trusted-peer = true ``` diff --git a/docs/plugins/validator.md b/docs/plugins/validator.md index c6202b8098..c331de515a 100644 --- a/docs/plugins/validator.md +++ b/docs/plugins/validator.md @@ -22,7 +22,7 @@ chain::plugin, p2p::p2p_plugin, snapshot::snapshot_plugin |--------|---------|-------------| | `validator` / `-w` | — | Validator account name(s); may be repeated | | `private-key` | — | WIF private key(s) for signing; may be repeated | -| `emergency-private-key` | — | WIF key for emergency consensus; auto-adds `CHAIN_EMERGENCY_WITNESS_ACCOUNT` to the validator set | +| `emergency-private-key` | — | WIF key for emergency consensus; auto-adds `CHAIN_EMERGENCY_VALIDATOR_ACCOUNT` to the validator set | | `enable-stale-production` | `false` | Bypass participation and sync checks (testnet / network recovery only) | | `required-participation` | `3300` | Minimum validator participation in **basis points** (3300 = 33%) | | `fork-collision-timeout-blocks` | `21` | Consecutive fork-collision deferrals before forcing production (one full validator round) | @@ -175,7 +175,7 @@ Returns `true` if a locally-controlled validator is scheduled to produce in the ### `is_emergency_master()` Returns `true` when: -1. `emergency-private-key` is configured (`CHAIN_EMERGENCY_WITNESS_ACCOUNT` in `_witnesses`). +1. `emergency-private-key` is configured (`CHAIN_EMERGENCY_VALIDATOR_ACCOUNT` in `_validators`). 2. The "committee" account is in the current validator schedule. Only nodes where both conditions hold should produce solo during emergency mode; others are followers and must sync first. diff --git a/docs/protocol/data-types.md b/docs/protocol/data-types.md index 8dd90ae123..3bb81e1659 100644 --- a/docs/protocol/data-types.md +++ b/docs/protocol/data-types.md @@ -159,9 +159,9 @@ Every operation is serialized as a 2-element array: `[type_id, operation_object] | 3 | `transfer_to_vesting_operation` | | 4 | `withdraw_vesting_operation` | | 5 | `account_update_operation` | -| 6 | `witness_update_operation` | -| 7 | `account_witness_vote_operation` | -| 8 | `account_witness_proxy_operation` | +| 6 | `validator_update_operation` | +| 7 | `account_validator_vote_operation` | +| 8 | `account_validator_proxy_operation` | | 9 | `delete_content_operation` *(deprecated)* | | 10 | `custom_operation` | | 11 | `set_withdraw_vesting_route_operation` | @@ -204,7 +204,7 @@ Every operation is serialized as a 2-element array: `[type_id, operation_object] | 27 | `curation_reward_operation` | | 28 | `content_reward_operation` | | 29 | `fill_vesting_withdraw_operation` | -| 30 | `shutdown_witness_operation` | +| 30 | `shutdown_validator_operation` | | 31 | `hardfork_operation` | | 32 | `content_payout_update_operation` | | 33 | `content_benefactor_reward_operation` | @@ -213,7 +213,7 @@ Every operation is serialized as a 2-element array: `[type_id, operation_object] | 39 | `committee_approve_request_operation` | | 40 | `committee_payout_request_operation` | | 41 | `committee_pay_request_operation` | -| 42 | `witness_reward_operation` | +| 42 | `validator_reward_operation` | | 48 | `receive_award_operation` | | 49 | `benefactor_award_operation` | | 52 | `paid_subscription_action_operation` | diff --git a/docs/protocol/operations/overview.md b/docs/protocol/operations/overview.md index 64ebf87e9e..6b695bc64d 100644 --- a/docs/protocol/operations/overview.md +++ b/docs/protocol/operations/overview.md @@ -16,9 +16,9 @@ These are user-initiated operations that can be broadcast to the network. | 3 | `transfer_to_vesting_operation` | active | [Transfers](./transfers.md) | | 4 | `withdraw_vesting_operation` | active | [Transfers](./transfers.md) | | 5 | `account_update_operation` | master / active | [Accounts](./accounts.md) | -| 6 | `witness_update_operation` | active | [Validators](./validators.md) | -| 7 | `account_witness_vote_operation` | active | [Validators](./validators.md) | -| 8 | `account_witness_proxy_operation` | active | [Validators](./validators.md) | +| 6 | `validator_update_operation` | active | [Validators](./validators.md) | +| 7 | `account_validator_vote_operation` | active | [Validators](./validators.md) | +| 8 | `account_validator_proxy_operation` | active | [Validators](./validators.md) | | 9 | `delete_content_operation` *(deprecated)* | regular | [Content](./content.md) | | 10 | `custom_operation` | active / regular | [Content](./content.md) | | 11 | `set_withdraw_vesting_route_operation` | active | [Transfers](./transfers.md) | @@ -65,7 +65,7 @@ Virtual operations are generated by the blockchain itself during block processin | 27 | `curation_reward_operation` | Content payout | [Virtual Ops](../virtual-operations.md) | | 28 | `content_reward_operation` | Content payout | [Virtual Ops](../virtual-operations.md) | | 29 | `fill_vesting_withdraw_operation` | Withdrawal interval fires | [Virtual Ops](../virtual-operations.md) | -| 30 | `shutdown_witness_operation` | Validator deactivated | [Virtual Ops](../virtual-operations.md) | +| 30 | `shutdown_validator_operation` | Validator deactivated | [Virtual Ops](../virtual-operations.md) | | 31 | `hardfork_operation` | Hardfork activation | [Virtual Ops](../virtual-operations.md) | | 32 | `content_payout_update_operation` | Content payout update | [Virtual Ops](../virtual-operations.md) | | 33 | `content_benefactor_reward_operation` | Content payout | [Virtual Ops](../virtual-operations.md) | @@ -74,7 +74,7 @@ Virtual operations are generated by the blockchain itself during block processin | 39 | `committee_approve_request_operation` | Committee request approved | [Virtual Ops](../virtual-operations.md) | | 40 | `committee_payout_request_operation` | Committee payout processed | [Virtual Ops](../virtual-operations.md) | | 41 | `committee_pay_request_operation` | Committee worker paid | [Virtual Ops](../virtual-operations.md) | -| 42 | `witness_reward_operation` | Block produced | [Virtual Ops](../virtual-operations.md) | +| 42 | `validator_reward_operation` | Block produced | [Virtual Ops](../virtual-operations.md) | | 48 | `receive_award_operation` | Award received | [Virtual Ops](../virtual-operations.md) | | 49 | `benefactor_award_operation` | Award with beneficiary | [Virtual Ops](../virtual-operations.md) | | 52 | `paid_subscription_action_operation` | Subscription payment | [Virtual Ops](../virtual-operations.md) | diff --git a/docs/protocol/operations/validators.md b/docs/protocol/operations/validators.md index 32bda4066f..5089314540 100644 --- a/docs/protocol/operations/validators.md +++ b/docs/protocol/operations/validators.md @@ -2,7 +2,7 @@ --- -## `witness_update_operation` (ID 6) +## `validator_update_operation` (ID 6) **Auth:** `active` of `owner` @@ -23,7 +23,7 @@ Registers or updates a validator node. Setting `block_signing_key` to the null k ``` - **Null key** (deactivate): `"VIZ1111111111111111111111111111111114T1Anm"` — removes from block production without deleting the validator record. -- Broadcasting this operation requires `witness_declaration_fee` (paid to the committee fund). +- Broadcasting this operation requires `validator_declaration_fee` (paid to the committee fund). --- @@ -91,18 +91,18 @@ Votes on versioned chain properties supporting all hardfork extensions. Preferre "flag_energy_additional_cost": 1000, "vote_accounting_min_rshares": 0, "committee_request_approve_min_percent": 1000, - "inflation_witness_percent": 2000, + "inflation_validator_percent": 2000, "inflation_ratio_committee_vs_reward_fund": 1000, "inflation_recalc_period": 28800, "data_operations_cost_additional_bandwidth": 0, - "witness_miss_penalty_percent": 100, - "witness_miss_penalty_duration": 86400, + "validator_miss_penalty_percent": 100, + "validator_miss_penalty_duration": 86400, "create_invite_min_balance": "1.000 VIZ", "committee_create_request_fee": "1.000 VIZ", "create_paid_subscription_fee": "1.000 VIZ", "account_on_sale_fee": "10.000 VIZ", "subaccount_on_sale_fee": "1.000 VIZ", - "witness_declaration_fee": "1.000 VIZ", + "validator_declaration_fee": "1.000 VIZ", "withdraw_intervals": 28 }] }] @@ -113,7 +113,7 @@ Votes on versioned chain properties supporting all hardfork extensions. Preferre --- -## `account_witness_vote_operation` (ID 7) +## `account_validator_vote_operation` (ID 7) **Auth:** `active` of `account` @@ -138,7 +138,7 @@ Votes for or removes a vote from a validator. The top 21 validators by cumulativ --- -## `account_witness_proxy_operation` (ID 8) +## `account_validator_proxy_operation` (ID 8) **Auth:** `active` of `account` diff --git a/docs/protocol/virtual-operations.md b/docs/protocol/virtual-operations.md index 9493436d75..6e38c7b3d7 100644 --- a/docs/protocol/virtual-operations.md +++ b/docs/protocol/virtual-operations.md @@ -115,7 +115,7 @@ Fired once per interval for each active withdrawal route. ## Validator Operations -### `shutdown_witness_operation` (ID 30) +### `shutdown_validator_operation` (ID 30) **Trigger:** Validator deactivated due to insufficient vote weight @@ -125,7 +125,7 @@ Fired once per interval for each active withdrawal route. --- -### `witness_reward_operation` (ID 42) +### `validator_reward_operation` (ID 42) **Trigger:** Block produced — validator receives block reward diff --git a/docs/storage/block-log.md b/docs/storage/block-log.md index d59079060b..26857b063d 100644 --- a/docs/storage/block-log.md +++ b/docs/storage/block-log.md @@ -77,7 +77,7 @@ block_header: [varint + vector: extensions] signed_block_header (appended): - [65 bytes: witness_signature (1 recovery byte + 32 r + 32 s)] + [65 bytes: validator_signature (1 recovery byte + 32 r + 32 s)] signed_block (appended): [varint + vector: transactions] diff --git a/docs/storage/snapshots.md b/docs/storage/snapshots.md index 1d89610d9d..9f0dfd9f1d 100644 --- a/docs/storage/snapshots.md +++ b/docs/storage/snapshots.md @@ -208,6 +208,7 @@ snapshot-dir = /data/viz-snapshots ```ini trusted-snapshot-peer = seed1.viz.world:8092 trusted-snapshot-peer = seed2.viz.world:8092 +trusted-snapshot-peer = seed3.viz.world:8092 sync-snapshot-from-trusted-peer = true ``` diff --git a/documentation/building.md b/documentation/building.md index 720cb2f156..40563a84fd 100644 --- a/documentation/building.md +++ b/documentation/building.md @@ -12,7 +12,7 @@ running tests, it is recommended to build as release. Builds vizd to be a consensus-only low memory node. Data and fields not needed for consensus are not stored in the object database. This option is -recommended for witnesses and seed-nodes. +recommended for validators and seed-nodes. ## Building under Docker diff --git a/documentation/debug_node_plugin.md b/documentation/debug_node_plugin.md index e617389155..a5fb66b35d 100644 --- a/documentation/debug_node_plugin.md +++ b/documentation/debug_node_plugin.md @@ -109,7 +109,7 @@ The important information in the above is: ... "signing_key":"STM6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" ... ... "head_block_number":1505 ... -which demonstrates the witness keys have been reset and the head block number has been advanced with new blocks. The blocks are signed by the above private key, and the database is edited to set the block signing key of the scheduled witnesses accordingly so the node accepts the simulated signatures as valid. +which demonstrates the validator keys have been reset and the head block number has been advanced with new blocks. The blocks are signed by the above private key, and the database is edited to set the block signing key of the scheduled validators accordingly so the node accepts the simulated signatures as valid. If we want to take control of an account we can do so by editing its key with `debug_update_object` command like this: diff --git a/libraries/chain/chain_evaluator.cpp b/libraries/chain/chain_evaluator.cpp index 132fd4d79a..d5da60ec85 100644 --- a/libraries/chain/chain_evaluator.cpp +++ b/libraries/chain/chain_evaluator.cpp @@ -1151,12 +1151,12 @@ namespace graphene { namespace chain { 0, "A proxy is currently set, please clear the proxy before voting for a validator."); } - const auto &witness = _db.get_witness(o.validator); + const auto &validator = _db.get_validator(o.validator); - const auto &by_account_witness_idx = _db.get_index().indices().get(); - auto itr = by_account_witness_idx.find(boost::make_tuple(voter.id, witness.id)); + const auto &by_account_validator_idx = _db.get_index().indices().get(); + auto itr = by_account_validator_idx.find(boost::make_tuple(voter.id, validator.id)); - if (itr == by_account_witness_idx.end()) { + if (itr == by_account_validator_idx.end()) { FC_ASSERT(o.approve, "Vote doesn't exist, user must indicate a desire to approve validator."); if(_db.has_hardfork(CHAIN_HARDFORK_4)){ @@ -1169,15 +1169,15 @@ namespace graphene { namespace chain { } if(_db.has_hardfork(CHAIN_HARDFORK_5)){ - const auto &vidx = _db.get_index().indices().get(); + const auto &vidx = _db.get_index().indices().get(); auto vitr = vidx.lower_bound(boost::make_tuple(voter.id, validator_id_type())); while (vitr != vidx.end() && vitr->account == voter.id) { - _db.adjust_validator_vote(_db.get(vitr->witness), -voter.validators_vote_weight); + _db.adjust_validator_vote(_db.get(vitr->validator), -voter.validators_vote_weight); ++vitr; } - _db.create([&](witness_vote_object &v) { - v.witness = witness.id; + _db.create([&](validator_vote_object &v) { + v.validator = validator.id; v.account = voter.id; v.vote_created_block = _db.head_block_num(); }); @@ -1190,23 +1190,23 @@ namespace graphene { namespace chain { a.validators_vote_weight = fair_vote_weight; }); - const auto &vidx2 = _db.get_index().indices().get(); + const auto &vidx2 = _db.get_index().indices().get(); auto vitr2 = vidx2.lower_bound(boost::make_tuple(voter.id, validator_id_type())); while (vitr2 != vidx2.end() && vitr2->account == voter.id) { - _db.adjust_validator_vote(_db.get(vitr2->witness), voter.validators_vote_weight); + _db.adjust_validator_vote(_db.get(vitr2->validator), voter.validators_vote_weight); ++vitr2; } } else if(_db.has_hardfork(CHAIN_HARDFORK_4)){ - const auto &vidx = _db.get_index().indices().get(); + const auto &vidx = _db.get_index().indices().get(); auto vitr = vidx.lower_bound(boost::make_tuple(voter.id, validator_id_type())); while (vitr != vidx.end() && vitr->account == voter.id) { - _db.adjust_validator_vote(_db.get(vitr->witness), -voter.validator_vote_fair_weight_prehf5()); + _db.adjust_validator_vote(_db.get(vitr->validator), -voter.validator_vote_fair_weight_prehf5()); ++vitr; } - _db.create([&](witness_vote_object &v) { - v.witness = witness.id; + _db.create([&](validator_vote_object &v) { + v.validator = validator.id; v.account = voter.id; v.vote_created_block = _db.head_block_num(); }); @@ -1215,20 +1215,20 @@ namespace graphene { namespace chain { a.validators_voted_for++; }); - const auto &vidx2 = _db.get_index().indices().get(); + const auto &vidx2 = _db.get_index().indices().get(); auto vitr2 = vidx2.lower_bound(boost::make_tuple(voter.id, validator_id_type())); while (vitr2 != vidx2.end() && vitr2->account == voter.id) { - _db.adjust_validator_vote(_db.get(vitr2->witness), voter.validator_vote_fair_weight_prehf5()); + _db.adjust_validator_vote(_db.get(vitr2->validator), voter.validator_vote_fair_weight_prehf5()); ++vitr2; } } else{ - _db.create([&](witness_vote_object &v) { - v.witness = witness.id; + _db.create([&](validator_vote_object &v) { + v.validator = validator.id; v.account = voter.id; v.vote_created_block = _db.head_block_num(); }); - _db.adjust_validator_vote(witness, voter.validator_vote_weight()); + _db.adjust_validator_vote(validator, voter.validator_vote_weight()); _db.modify(voter, [&](account_object &a) { a.validators_voted_for++; }); @@ -1237,10 +1237,10 @@ namespace graphene { namespace chain { FC_ASSERT(!o.approve, "Vote currently exists, user must indicate a desire to reject validator."); if(_db.has_hardfork(CHAIN_HARDFORK_5)){ - const auto &vidx = _db.get_index().indices().get(); + const auto &vidx = _db.get_index().indices().get(); auto vitr = vidx.lower_bound(boost::make_tuple(voter.id, validator_id_type())); while (vitr != vidx.end() && vitr->account == voter.id) { - _db.adjust_validator_vote(_db.get(vitr->witness), -voter.validators_vote_weight); + _db.adjust_validator_vote(_db.get(vitr->validator), -voter.validators_vote_weight); ++vitr; } @@ -1254,18 +1254,18 @@ namespace graphene { namespace chain { a.validators_vote_weight = fair_vote_weight; }); - const auto &vidx2 = _db.get_index().indices().get(); + const auto &vidx2 = _db.get_index().indices().get(); auto vitr2 = vidx2.lower_bound(boost::make_tuple(voter.id, validator_id_type())); while (vitr2 != vidx2.end() && vitr2->account == voter.id) { - _db.adjust_validator_vote(_db.get(vitr2->witness), voter.validators_vote_weight); + _db.adjust_validator_vote(_db.get(vitr2->validator), voter.validators_vote_weight); ++vitr2; } } else if(_db.has_hardfork(CHAIN_HARDFORK_4)){ - const auto &vidx = _db.get_index().indices().get(); + const auto &vidx = _db.get_index().indices().get(); auto vitr = vidx.lower_bound(boost::make_tuple(voter.id, validator_id_type())); while (vitr != vidx.end() && vitr->account == voter.id) { - _db.adjust_validator_vote(_db.get(vitr->witness), -voter.validator_vote_fair_weight_prehf5()); + _db.adjust_validator_vote(_db.get(vitr->validator), -voter.validator_vote_fair_weight_prehf5()); ++vitr; } @@ -1275,15 +1275,15 @@ namespace graphene { namespace chain { a.validators_voted_for--; }); - const auto &vidx2 = _db.get_index().indices().get(); + const auto &vidx2 = _db.get_index().indices().get(); auto vitr2 = vidx2.lower_bound(boost::make_tuple(voter.id, validator_id_type())); while (vitr2 != vidx2.end() && vitr2->account == voter.id) { - _db.adjust_validator_vote(_db.get(vitr2->witness), voter.validator_vote_fair_weight_prehf5()); + _db.adjust_validator_vote(_db.get(vitr2->validator), voter.validator_vote_fair_weight_prehf5()); ++vitr2; } } else{ - _db.adjust_validator_vote(witness, -voter.validator_vote_weight()); + _db.adjust_validator_vote(validator, -voter.validator_vote_weight()); _db.modify(voter, [&](account_object &a) { a.validators_voted_for--; }); @@ -1564,7 +1564,7 @@ namespace graphene { namespace chain { if (account_to_recover.recovery_account.length()) // Make sure recovery matches expected recovery account FC_ASSERT(account_to_recover.recovery_account == o.recovery_account, "Cannot recover an account that does not have you as there recovery partner."); - else // Empty string recovery account defaults to top witness + else // Empty string recovery account defaults to top validator FC_ASSERT( _db.get_index().indices().get().begin()->owner == o.recovery_account, "Top validator must recover an account with no recovery partner."); diff --git a/libraries/chain/database.cpp b/libraries/chain/database.cpp index 9944561424..10fafcb33b 100644 --- a/libraries/chain/database.cpp +++ b/libraries/chain/database.cpp @@ -430,9 +430,9 @@ namespace graphene { namespace chain { // === HARDFORK 12: EMERGENCY SCHEDULE RECOVERY === // If the node shut down (or crashed) during emergency mode while - // update_witness_schedule() had zeroed the schedule but before the + // update_validator_schedule() had zeroed the schedule but before the // hybrid override could fill it with committee, the schedule may - // contain empty (null) witness names. Since commit(LIB) may have + // contain empty (null) validator names. Since commit(LIB) may have // already made these changes permanent, the normal undo rollback // cannot fix this. Detect and repair it here on startup. if (head_block_num() > 0) { @@ -554,7 +554,7 @@ namespace graphene { namespace chain { skip_transaction_dupe_check | skip_tapos_check | skip_merkle_check | - skip_witness_schedule_check | + skip_validator_schedule_check | skip_authority_check | skip_validate_operations | /// no need to validate operations skip_block_log; @@ -674,7 +674,7 @@ namespace graphene { namespace chain { skip_transaction_dupe_check | skip_tapos_check | skip_merkle_check | - skip_witness_schedule_check | + skip_validator_schedule_check | skip_authority_check | skip_validate_operations | skip_block_log; @@ -818,7 +818,7 @@ namespace graphene { namespace chain { // Use the resize barrier to pause ALL database operations. // This is stronger than with_strong_write_lock: it also blocks // lockless reads (e.g. get_slot_at_time, get_scheduled_validator, - // find_account in _generate_block and witness plugin) that do not + // find_account in _generate_block and validator plugin) that do not // acquire any chainbase lock. After begin_resize_barrier() // returns, no thread holds any reference into shared memory. ilog("Resize barrier: pausing all database operations..."); @@ -1151,13 +1151,13 @@ namespace graphene { namespace chain { return CHAIN_ID; } - const validator_object &database::get_witness(const account_name_type &name) const { + const validator_object &database::get_validator(const account_name_type &name) const { try { return get(name); } FC_CAPTURE_AND_RETHROW((name)) } - const validator_object *database::find_witness(const account_name_type &name) const { + const validator_object *database::find_validator(const account_name_type &name) const { return find(name); } @@ -1286,7 +1286,7 @@ namespace graphene { namespace chain { return has_bandwidth; } - uint32_t database::witness_participation_rate() const { + uint32_t database::validator_participation_rate() const { const dynamic_global_property_object &dpo = get_dynamic_global_properties(); return uint64_t(CHAIN_100_PERCENT) * dpo.recent_slots_filled.popcount() / 128; @@ -1432,10 +1432,10 @@ namespace graphene { namespace chain { void database::_maybe_warn_multiple_production(uint32_t height) const { auto blocks = _fork_db.fetch_block_by_number(height); if (blocks.size() > 1) { - vector> witness_time_pairs; + vector> validator_time_pairs; vector previous_ids; for (const auto &b : blocks) { - witness_time_pairs.push_back(std::make_pair(b->data.validator, b->data.timestamp)); + validator_time_pairs.push_back(std::make_pair(b->data.validator, b->data.timestamp)); previous_ids.push_back(b->data.previous); } @@ -1471,11 +1471,11 @@ namespace graphene { namespace chain { if (same_parent) { wlog("Block num collision at block ${n}: ${cnt} blocks with SAME parent " "(possible double-production), time_delta=${td}s, validators: ${w}", - ("n", height)("cnt", blocks.size())("td", time_delta_sec)("w", witness_time_pairs)); + ("n", height)("cnt", blocks.size())("td", time_delta_sec)("w", validator_time_pairs)); } else { wlog("Block num collision at block ${n}: ${cnt} blocks with DIFFERENT parents " "(fork from divergent chain tips), time_delta=${td}s, validators: ${w}", - ("n", height)("cnt", blocks.size())("td", time_delta_sec)("w", witness_time_pairs)); + ("n", height)("cnt", blocks.size())("td", time_delta_sec)("w", validator_time_pairs)); } // Log previous block IDs for fork topology analysis @@ -1494,7 +1494,7 @@ namespace graphene { namespace chain { auto branches = _fork_db.fetch_branch_from(branch_a_tip, branch_b_tip); auto compute_branch_info = [&](const fork_database::branch_type& branch) -> std::pair { - flat_set seen_witnesses; + flat_set seen_validators; share_type total_weight = 0; bool has_emergency = false; for (const auto& item : branch) { @@ -1503,9 +1503,9 @@ namespace graphene { namespace chain { has_emergency = true; continue; } - if (seen_witnesses.insert(wit_name).second) { + if (seen_validators.insert(wit_name).second) { try { - const auto& wit_obj = get_witness(wit_name); + const auto& wit_obj = get_validator(wit_name); total_weight += wit_obj.votes; } catch (...) {} } @@ -1520,7 +1520,7 @@ namespace graphene { namespace chain { auto weight_b = branch_info_b.first; auto emergency_b = branch_info_b.second; - // In emergency consensus mode, the emergency committee witness + // In emergency consensus mode, the emergency committee validator // represents the collective authority of the committee. Since // the committee account has no vote weight, directly assign its // chain as the main fork: if one branch has emergency committee @@ -1533,7 +1533,7 @@ namespace graphene { namespace chain { } // Longer chain gets +10% bonus on its vote weight. - // Each block produced is a consensus "vote" — witnesses on the longer + // Each block produced is a consensus "vote" — validators on the longer // chain didn't defer and kept producing by consensus rules. // This reflects the stronger network support signal. auto a_num = block_header::num_from_id(branch_a_tip); @@ -1689,7 +1689,7 @@ namespace graphene { namespace chain { // unlinkable_block_exception inside fork_db::_push_block() // ("block does not link to known chain"), silently rejecting // valid next-blocks and preventing head advancement. - // This also fixes witness nodes that generate their own + // This also fixes validator nodes that generate their own // blocks: generate_block() sets pending_block.previous = // head_block_id(), and without the seed the self-generated // block would fail to push into fork_db. @@ -1878,6 +1878,8 @@ namespace graphene { namespace chain { ? block_id_type() : branches.second.back()->data.id(); + bool schedule_was_relaxed = false; + for (auto ritr = branches.first.rbegin(); ritr != branches.first.rend(); ++ritr) { if (is_linear_extension && @@ -1900,8 +1902,9 @@ namespace graphene { namespace chain { ("n", (*ritr)->data.block_num())("w", (*ritr)->data.validator)("e", e.to_detail_string())); try { auto session = start_undo_session(); - apply_block((*ritr)->data, skip | skip_witness_schedule_check); + apply_block((*ritr)->data, skip | skip_validator_schedule_check); session.push(); + schedule_was_relaxed = true; } catch (const fc::exception &e2) { except = e2; } @@ -1983,6 +1986,45 @@ namespace graphene { namespace chain { } } + // Auto-correct current_aslot if a persistent schedule + // offset was detected during a linear extension. In a + // linear extension the blocks ARE the correct next blocks + // for this chain — a schedule mismatch means our + // current_aslot drifted (e.g. from snapshot import or a + // prior unclean fork switch). Verify by checking that + // the head block's validator occupies the expected + // position in the schedule: after apply_block, + // shuffled[current_aslot % num] must equal block.validator. + if (schedule_was_relaxed && is_linear_extension) { + const auto &corr_dpo = get_dynamic_global_properties(); + const auto &corr_wso = get_validator_schedule_object(); + uint32_t num = corr_wso.num_scheduled_validators; + if (num > 0) { + uint64_t cur_pos = corr_dpo.current_aslot % num; + // Find actual position of head block's validator + int actual_pos = -1; + for (int i = 0; i < num; ++i) { + if (corr_wso.current_shuffled_validators[i] == new_head->data.validator) { + actual_pos = i; + break; + } + } + if (actual_pos >= 0 && (uint64_t)actual_pos != cur_pos) { + int64_t delta = (int64_t)actual_pos - (int64_t)cur_pos; + if (delta < 0) delta += num; + wlog("Schedule offset auto-correction: current_aslot=${a} " + "(pos=${cp}) but head validator '${v}' is at pos=${ap}. " + "Adjusting current_aslot by +${d}.", + ("a", corr_dpo.current_aslot)("cp", cur_pos) + ("v", new_head->data.validator)("ap", actual_pos) + ("d", delta)); + modify(corr_dpo, [&](dynamic_global_property_object &dgp) { + dgp.current_aslot += delta; + }); + } + } + } + // After successfully switching to the new fork, update the // fork_db head to point to the new chain tip. pop_block() // moves _head backwards via _fork_db.pop_block(), but @@ -2008,7 +2050,7 @@ namespace graphene { namespace chain { // Schedule mismatch: keep the block in fork_db as a // competing tip so descendants can link to it. When // a heavier branch builds upon this block, fork-switch - // will apply it with skip_witness_schedule_check. + // will apply it with skip_validator_schedule_check. // Returning false signals "not applied" without // triggering the P2P rejection / soft-ban path. wlog("Block #${n} from validator ${w} kept in fork_db as competing tip (schedule mismatch): ${e}", @@ -2178,27 +2220,27 @@ namespace graphene { namespace chain { signed_block database::generate_block( fc::time_point_sec when, - const account_name_type &witness_owner, + const account_name_type &validator_owner, const fc::ecc::private_key &block_signing_private_key, uint32_t skip /* = 0 */ ) { signed_block result; try { - result = _generate_block(when, witness_owner, block_signing_private_key, skip); + result = _generate_block(when, validator_owner, block_signing_private_key, skip); } - FC_CAPTURE_AND_RETHROW((witness_owner)) + FC_CAPTURE_AND_RETHROW((validator_owner)) return result; } signed_block database::_generate_block( fc::time_point_sec when, - const account_name_type &witness_owner, + const account_name_type &validator_owner, const fc::ecc::private_key &block_signing_private_key, uint32_t skip ) { // Apply any deferred resize BEFORE the lockless reads below. - // This is critical: get_slot_at_time(), get_witness(), find_account() + // This is critical: get_slot_at_time(), get_validator(), find_account() // all read from chainbase indices without holding a read lock. // If resize happened on another thread, those pointers could be stale. apply_pending_resize(); @@ -2213,39 +2255,39 @@ namespace graphene { namespace chain { uint32_t slot_num = get_slot_at_time(when); FC_ASSERT(slot_num > 0); - string scheduled_witness = get_scheduled_validator(slot_num); - FC_ASSERT(scheduled_witness == witness_owner); + string scheduled_validator = get_scheduled_validator(slot_num); + FC_ASSERT(scheduled_validator == validator_owner); - const auto &witness_obj = get_witness(witness_owner); + const auto &validator_obj = get_validator(validator_owner); - // Pre-check: ensure the witness account exists before generating the block. + // Pre-check: ensure the validator account exists before generating the block. // If the account is missing from the database (shared memory corruption), // the block will be produced but fail to apply internally (process_funds // calls get_account which would throw "unknown key"). - const auto* witness_acct = find_account(witness_owner); - if (!witness_acct) { + const auto* validator_acct = find_account(validator_owner); + if (!validator_acct) { auto& acc_idx = get_index().indices().get(); elog("CRITICAL: Validator ${w} account object MISSING from database! " "This is impossible state - shared memory may be corrupted. " "signing_key=${k} total_missed=${m} penalty=${p} last_confirmed=${lc} " "account_index_size=${idx_size}", - ("w", witness_owner)("k", witness_obj.signing_key) - ("m", witness_obj.total_missed)("p", witness_obj.penalty_percent) - ("lc", witness_obj.last_confirmed_block_num) + ("w", validator_owner)("k", validator_obj.signing_key) + ("m", validator_obj.total_missed)("p", validator_obj.penalty_percent) + ("lc", validator_obj.last_confirmed_block_num) ("idx_size", acc_idx.size())); FC_THROW_EXCEPTION(shared_memory_corruption_exception, "CRITICAL: Validator ${w} account not found in database! Shared memory corruption suspected.", - ("w", witness_owner)); + ("w", validator_owner)); } if (!(skip & skip_validator_signature)) - FC_ASSERT(witness_obj.signing_key == + FC_ASSERT(validator_obj.signing_key == block_signing_private_key.get_public_key()); } // op_guard released here // Second operation guard covers all remaining lockless reads // in this function: get_dynamic_global_properties(), head_block_id(), - // get_witness(), get_hardfork_property_object(). Released before + // get_validator(), get_hardfork_property_object(). Released before // push_block() which has its own guards. auto op_guard2 = make_operation_guard(); @@ -2322,17 +2364,17 @@ namespace graphene { namespace chain { pending_block.previous = head_block_id(); pending_block.timestamp = when; pending_block.transaction_merkle_root = pending_block.calculate_merkle_root(); - pending_block.validator = witness_owner; + pending_block.validator = validator_owner; - const auto &witness = get_witness(witness_owner); + const auto &validator = get_validator(validator_owner); - if (witness.running_version != CHAIN_VERSION) { + if (validator.running_version != CHAIN_VERSION) { pending_block.extensions.insert(block_header_extensions(CHAIN_VERSION)); } const auto &hfp = get_hardfork_property_object(); - // Emergency committee witness should NOT vote for future hardforks + // Emergency committee validator should NOT vote for future hardforks // via block extensions. Its on-chain vote is set to // current_hardfork_version (status quo) and is synced every // schedule update. Auto-injection would overwrite this and @@ -2342,14 +2384,14 @@ namespace graphene { namespace chain { bool is_emergency_committee = has_hardfork(CHAIN_HARDFORK_12) && dgp_block.emergency_consensus_active && - witness_owner == CHAIN_EMERGENCY_VALIDATOR_ACCOUNT; + validator_owner == CHAIN_EMERGENCY_VALIDATOR_ACCOUNT; if (!is_emergency_committee) { if (hfp.current_hardfork_version < CHAIN_HARDFORK_VERSION // Binary is newer hardfork than has been applied - && (witness.hardfork_version_vote != + && (validator.hardfork_version_vote != _hardfork_versions[hfp.last_hardfork + 1] || - witness.hardfork_time_vote != + validator.hardfork_time_vote != _hardfork_times[hfp.last_hardfork + 1])) // Witness vote does not match binary configuration { @@ -2359,7 +2401,7 @@ namespace graphene { namespace chain { hfp.last_hardfork + 1]))); } else if (hfp.current_hardfork_version == CHAIN_HARDFORK_VERSION // Binary does not know of a new hardfork - && witness.hardfork_version_vote > + && validator.hardfork_version_vote > CHAIN_HARDFORK_VERSION) // Voting for hardfork in the future, that we do not know of... { // Make vote match binary configuration. This is vote to not apply the new hardfork. @@ -2378,7 +2420,7 @@ namespace graphene { namespace chain { op_guard2.release(); // release before push_block(), which has its own guards - if (_debug_block_production) ilog("DEBUG_CRASH: push_block start for block by ${w}", ("w", witness_owner)); + if (_debug_block_production) ilog("DEBUG_CRASH: push_block start for block by ${w}", ("w", validator_owner)); push_block(pending_block, skip); if (_debug_block_production) ilog("DEBUG_CRASH: push_block done"); @@ -2796,21 +2838,21 @@ namespace graphene { namespace chain { } } - void database::update_witness_schedule() { + void database::update_validator_schedule() { if ((head_block_num() % ( CHAIN_MAX_VALIDATORS * CHAIN_BLOCK_VALIDATOR_REPEAT ) ) != 0) return; if (_debug_block_production) ilog("DEBUG_CRASH: update_validator_schedule ENTER at block ${b}", ("b", head_block_num())); - if(has_hardfork(CHAIN_HARDFORK_6)){//remove expired witness penalty - const auto &idx = get_index().indices().get(); + if(has_hardfork(CHAIN_HARDFORK_6)){//remove expired validator penalty + const auto &idx = get_index().indices().get(); auto itr = idx.begin(); while(itr != idx.end()) { const auto ¤t = *itr; ++itr; if(current.expires <= head_block_time()){ - const auto &witness_obj = get_witness(current.witness); - modify(witness_obj, [&](validator_object &w) { + const auto &validator_obj = get_validator(current.validator); + modify(validator_obj, [&](validator_object &w) { w.penalty_percent-=current.penalty_percent; w.counted_votes=(fc::uint128_t(w.votes) - (fc::uint128_t(w.votes) * std::min(w.penalty_percent,uint32_t(CHAIN_100_PERCENT)) / CHAIN_100_PERCENT )).to_uint64(); }); @@ -2819,13 +2861,13 @@ namespace graphene { namespace chain { } } - vector active_witnesses; - active_witnesses.reserve(CHAIN_MAX_VALIDATORS); + vector active_validators; + active_validators.reserve(CHAIN_MAX_VALIDATORS); - vector support_witnesses; - support_witnesses.reserve(CHAIN_MAX_VALIDATORS); + vector support_validators; + support_validators.reserve(CHAIN_MAX_VALIDATORS); - /// Add the highest voted witnesses + /// Add the highest voted validators flat_set selected_voted; selected_voted.reserve(CHAIN_MAX_TOP_VALIDATORS); @@ -2837,51 +2879,51 @@ namespace graphene { namespace chain { if (itr->signing_key == public_key_type()) { continue; } - // Exclude committee/emergency witness from top witness selection. + // Exclude committee/emergency validator from top validator selection. // It fills gaps via the hybrid schedule, not through normal voting. if (has_hardfork(CHAIN_HARDFORK_12) && itr->owner == CHAIN_EMERGENCY_VALIDATOR_ACCOUNT) { continue; } selected_voted.insert(itr->id); - active_witnesses.push_back(itr->owner); + active_validators.push_back(itr->owner); modify(*itr, [&](validator_object &wo) { wo.schedule = validator_object::top; }); } - /// Add the running witnesses in the lead + /// Add the running validators in the lead const validator_schedule_object &wso = get_validator_schedule_object(); fc::uint128_t new_virtual_time = wso.current_virtual_time; const auto &schedule_idx = get_index().indices().get(); auto sitr = schedule_idx.begin(); - vector processed_witnesses; - for (auto witness_count = selected_voted.size(); + vector processed_validators; + for (auto validator_count = selected_voted.size(); sitr != schedule_idx.end() && - witness_count < CHAIN_MAX_VALIDATORS; + validator_count < CHAIN_MAX_VALIDATORS; ++sitr) { new_virtual_time = sitr->virtual_scheduled_time; /// everyone advances to at least this time - processed_witnesses.push_back(sitr); + processed_validators.push_back(sitr); if (sitr->signing_key == public_key_type()) { continue; - } /// skip witnesses without a valid block signing key + } /// skip validators without a valid block signing key - // Exclude committee/emergency witness from support selection + // Exclude committee/emergency validator from support selection if (has_hardfork(CHAIN_HARDFORK_12) && sitr->owner == CHAIN_EMERGENCY_VALIDATOR_ACCOUNT) { continue; } if (selected_voted.find(sitr->id) == selected_voted.end()) { - support_witnesses.push_back(sitr->owner); + support_validators.push_back(sitr->owner); modify(*sitr, [&](validator_object &wo) { wo.schedule = validator_object::support; }); - ++witness_count; + ++validator_count; } } - /// Update virtual schedule of processed witnesses + /// Update virtual schedule of processed validators bool reset_virtual_time = false; - for (auto itr = processed_witnesses.begin(); - itr != processed_witnesses.end(); ++itr) { + for (auto itr = processed_validators.begin(); + itr != processed_validators.end(); ++itr) { auto new_virtual_scheduled_time = new_virtual_time + VIRTUAL_SCHEDULE_LAP_LENGTH2 / ((*itr)->counted_votes.value + 1); @@ -2900,12 +2942,12 @@ namespace graphene { namespace chain { reset_virtual_schedule_time(); } - FC_ASSERT( ( active_witnesses.size() + support_witnesses.size() ) <= CHAIN_MAX_VALIDATORS, "Number of active validators cannot be more than CHAIN_MAX_VALIDATORS", - ("active_validators.size()", active_witnesses.size())("support_validators.size()", support_witnesses.size())("CHAIN_MAX_VALIDATORS", CHAIN_MAX_VALIDATORS)); + FC_ASSERT( ( active_validators.size() + support_validators.size() ) <= CHAIN_MAX_VALIDATORS, "Number of active validators cannot be more than CHAIN_MAX_VALIDATORS", + ("active_validators.size()", active_validators.size())("support_validators.size()", support_validators.size())("CHAIN_MAX_VALIDATORS", CHAIN_MAX_VALIDATORS)); auto majority_version = wso.majority_version; - flat_map> witness_versions; + flat_map> validator_versions; flat_map, uint32_t> hardfork_version_votes; const dynamic_global_property_object &_dgp = get_dynamic_global_properties(); @@ -2913,10 +2955,10 @@ namespace graphene { namespace chain { for (uint32_t i = 0; i < wso.num_scheduled_validators; i+=CHAIN_BLOCK_VALIDATOR_REPEAT) { auto wname = wso.current_shuffled_validators[i]; - // During emergency mode, exclude committee witness from hardfork vote tally. + // During emergency mode, exclude committee validator from hardfork vote tally. // Committee occupies multiple schedule slots but is a single entity with // default (0.0.0) version fields. Counting it would: - // - Inflate its vote weight (counted once per slot, not once per witness) + // - Inflate its vote weight (counted once per slot, not once per validator) // - Drag majority_version to 0.0.0 // - Block any hardfork from reaching CHAIN_HARDFORK_REQUIRED_VALIDATORS if (has_hardfork(CHAIN_HARDFORK_12) && _dgp.emergency_consensus_active && @@ -2924,15 +2966,15 @@ namespace graphene { namespace chain { continue; } - auto witness = get_witness(wname); - if (witness_versions.find(witness.running_version) == - witness_versions.end()) { - witness_versions[witness.running_version] = 1; + auto validator = get_validator(wname); + if (validator_versions.find(validator.running_version) == + validator_versions.end()) { + validator_versions[validator.running_version] = 1; } else { - witness_versions[witness.running_version] += 1; + validator_versions[validator.running_version] += 1; } - auto version_vote = std::make_tuple(witness.hardfork_version_vote, witness.hardfork_time_vote); + auto version_vote = std::make_tuple(validator.hardfork_version_vote, validator.hardfork_time_vote); if (hardfork_version_votes.find(version_vote) == hardfork_version_votes.end()) { hardfork_version_votes[version_vote] = 1; @@ -2941,14 +2983,14 @@ namespace graphene { namespace chain { } } - int witnesses_on_version = 0; - auto ver_itr = witness_versions.begin(); + int validators_on_version = 0; + auto ver_itr = validator_versions.begin(); - // The map should be sorted highest version to smallest, so we iterate until we hit the majority of witnesses on at least this version - while (ver_itr != witness_versions.end()) { - witnesses_on_version += ver_itr->second; + // The map should be sorted highest version to smallest, so we iterate until we hit the majority of validators on at least this version + while (ver_itr != validator_versions.end()) { + validators_on_version += ver_itr->second; - if (witnesses_on_version >= + if (validators_on_version >= CHAIN_HARDFORK_REQUIRED_VALIDATORS) { majority_version = ver_itr->first; break; @@ -2985,41 +3027,41 @@ namespace graphene { namespace chain { } if (_debug_block_production) ilog("DEBUG_CRASH: schedule normal build: active=${a} support=${s}", - ("a", active_witnesses.size())("s", support_witnesses.size())); + ("a", active_validators.size())("s", support_validators.size())); modify(wso, [&](validator_schedule_object &_wso) { - // active witnesses has exactly CHAIN_MAX_VALIDATORS elements, asserted above + // active validators has exactly CHAIN_MAX_VALIDATORS elements, asserted above size_t j = 0; - size_t support_witnesses_count = support_witnesses.size(); - size_t active_witnesses_count = active_witnesses.size(); - size_t sum_witnesses_count = support_witnesses_count+active_witnesses_count; - for( size_t i = 0; i < sum_witnesses_count; i++ ) + size_t support_validators_count = support_validators.size(); + size_t active_validators_count = active_validators.size(); + size_t sum_validators_count = support_validators_count+active_validators_count; + for( size_t i = 0; i < sum_validators_count; i++ ) { - if(active_witnesses_count > 0){ - --active_witnesses_count; + if(active_validators_count > 0){ + --active_validators_count; for(int repeat=0; repeat < CHAIN_BLOCK_VALIDATOR_REPEAT; ++repeat){ - _wso.current_shuffled_validators[j] = active_witnesses[i]; + _wso.current_shuffled_validators[j] = active_validators[i]; ++j; } } - if(support_witnesses_count > 0){ - --support_witnesses_count; + if(support_validators_count > 0){ + --support_validators_count; for(int repeat=0; repeat < CHAIN_BLOCK_VALIDATOR_REPEAT; ++repeat){ - _wso.current_shuffled_validators[j] = support_witnesses[i]; + _wso.current_shuffled_validators[j] = support_validators[i]; ++j; } } } - for (size_t i = sum_witnesses_count * CHAIN_BLOCK_VALIDATOR_REPEAT; + for (size_t i = sum_validators_count * CHAIN_BLOCK_VALIDATOR_REPEAT; i < ( CHAIN_MAX_VALIDATORS * CHAIN_BLOCK_VALIDATOR_REPEAT ); i++) { _wso.current_shuffled_validators[i] = account_name_type(); } - _wso.num_scheduled_validators = std::max(sum_witnesses_count * CHAIN_BLOCK_VALIDATOR_REPEAT , 1); + _wso.num_scheduled_validators = std::max(sum_validators_count * CHAIN_BLOCK_VALIDATOR_REPEAT , 1); /* // VIZ remove randomization - /// shuffle current shuffled witnesses + /// shuffle current shuffled validators auto now_hi = uint64_t(head_block_time().sec_since_epoch()) << 32; for (uint32_t i = 0; i < _wso.num_scheduled_validators; ++i) { @@ -3048,27 +3090,27 @@ namespace graphene { namespace chain { ("n", wso.num_scheduled_validators)); // === HARDFORK 12: EMERGENCY HYBRID SCHEDULE === - // Must run BEFORE update_median_witness_props() because the normal - // schedule above may have zeroed all slots (no witnesses have valid keys + // Must run BEFORE update_median_validator_props() because the normal + // schedule above may have zeroed all slots (no validators have valid keys // during emergency). The hybrid override fills empty slots with committee. const dynamic_global_property_object &emergency_dgp = get_dynamic_global_properties(); if (has_hardfork(CHAIN_HARDFORK_12) && emergency_dgp.emergency_consensus_active) { if (_debug_block_production) ilog("DEBUG_CRASH: hybrid override ENTER"); const validator_schedule_object &emergency_wso = get_validator_schedule_object(); - uint32_t real_witness_slots = 0; + uint32_t real_validator_slots = 0; uint32_t committee_slots = 0; modify(emergency_wso, [&](validator_schedule_object &_wso) { // First pass: replace unavailable/empty slots with committee // Iterate the FULL schedule (CHAIN_MAX_VALIDATORS), not just - // num_scheduled_witnesses, because the normal schedule may have - // set num_scheduled_witnesses < CHAIN_MAX_VALIDATORS when fewer - // witnesses have valid signing keys. + // num_scheduled_validators, because the normal schedule may have + // set num_scheduled_validators < CHAIN_MAX_VALIDATORS when fewer + // validators have valid signing keys. for (int i = 0; i < CHAIN_MAX_VALIDATORS; i += CHAIN_BLOCK_VALIDATOR_REPEAT) { - // Read from slot i, but only if within current num_scheduled_witnesses + // Read from slot i, but only if within current num_scheduled_validators const auto &wname = (i < _wso.num_scheduled_validators) ? _wso.current_shuffled_validators[i] : account_name_type(); @@ -3083,22 +3125,22 @@ namespace graphene { namespace chain { continue; } - const auto *w = find_witness(wname); - bool witness_available = w && + const auto *w = find_validator(wname); + bool validator_available = w && w->signing_key != public_key_type(); - if (!witness_available) { + if (!validator_available) { for (int j = 0; j < CHAIN_BLOCK_VALIDATOR_REPEAT; ++j) { _wso.current_shuffled_validators[i+j] = CHAIN_EMERGENCY_VALIDATOR_ACCOUNT; } committee_slots++; } else { - real_witness_slots++; + real_validator_slots++; } } - // Expand num_scheduled_witnesses to CHAIN_MAX_VALIDATORS so that + // Expand num_scheduled_validators to CHAIN_MAX_VALIDATORS so that // committee slots are included in the production cycle. _wso.num_scheduled_validators = CHAIN_MAX_VALIDATORS * CHAIN_BLOCK_VALIDATOR_REPEAT; _wso.next_shuffle_block_num = @@ -3106,16 +3148,16 @@ namespace graphene { namespace chain { dlog(DB_LOG_YELLOW "Emergency hybrid schedule: ${r} real validator slots, " "${c} committee slots" DB_LOG_RESET, - ("r", real_witness_slots) + ("r", real_validator_slots) ("c", committee_slots)); }); if (_debug_block_production) ilog("DEBUG_CRASH: hybrid override done, real=${r} committee=${c} num_scheduled=${n}", - ("r", real_witness_slots)("c", committee_slots)("n", emergency_wso.num_scheduled_validators)); + ("r", real_validator_slots)("c", committee_slots)("n", emergency_wso.num_scheduled_validators)); - // Sync committee witness props/hardfork-vote with the latest median + // Sync committee validator props/hardfork-vote with the latest median // and current hardfork state. This runs every schedule update so that - // if real witnesses change their chain_properties during emergency, the + // if real validators change their chain_properties during emergency, the // committee's props stay in sync and don't skew the next median // computation. Also keeps hardfork vote aligned with the currently // applied on-chain version. @@ -3132,11 +3174,11 @@ namespace graphene { namespace chain { } - // EXIT CONDITION: enough real witnesses have re-enabled. - // When >= 75% of schedule slots are real witnesses (not committee), + // EXIT CONDITION: enough real validators have re-enabled. + // When >= 75% of schedule slots are real validators (not committee), // the network has recovered and can sustain normal consensus. uint32_t exit_threshold = (CHAIN_MAX_VALIDATORS * CHAIN_IRREVERSIBLE_THRESHOLD) / CHAIN_100_PERCENT; - if (real_witness_slots >= exit_threshold) { + if (real_validator_slots >= exit_threshold) { modify(emergency_dgp, [&](dynamic_global_property_object &_dgp) { _dgp.emergency_consensus_active = false; }); @@ -3147,35 +3189,35 @@ namespace graphene { namespace chain { ilog("EMERGENCY CONSENSUS MODE deactivated at block ${b}. " "${r} real validators active (threshold: ${t}).", ("b", head_block_num()) - ("r", real_witness_slots) + ("r", real_validator_slots) ("t", exit_threshold)); } } - update_median_witness_props(); + update_median_validator_props(); } - void database::update_median_witness_props() { + void database::update_median_validator_props() { const validator_schedule_object &wso = get_validator_schedule_object(); const dynamic_global_property_object &median_dgp = get_dynamic_global_properties(); - /// fetch all witness objects (excluding committee during emergency) + /// fetch all validator objects (excluding committee during emergency) vector active; active.reserve(wso.num_scheduled_validators); for (int i = 0; i < wso.num_scheduled_validators; i+=CHAIN_BLOCK_VALIDATOR_REPEAT) { const auto &wname = wso.current_shuffled_validators[i]; - // During emergency mode, exclude committee witness from median computation. + // During emergency mode, exclude committee validator from median computation. // Committee has default chain_properties (zero fees, zero sizes) and // occupies multiple schedule slots, which would skew the median. if (has_hardfork(CHAIN_HARDFORK_12) && median_dgp.emergency_consensus_active && wname == CHAIN_EMERGENCY_VALIDATOR_ACCOUNT) { continue; } - active.push_back(&get_witness(wname)); + active.push_back(&get_validator(wname)); } if (active.empty()) { - // All committee, no real witnesses to compute median from. + // All committee, no real validators to compute median from. // Keep existing median_props unchanged. return; } @@ -3289,34 +3331,34 @@ namespace graphene { namespace chain { } void database::adjust_validator_votes(const account_object &a, share_type delta) { - if(has_hardfork(CHAIN_HARDFORK_5)){//need to clear witness vote weight + if(has_hardfork(CHAIN_HARDFORK_5)){//need to clear validator vote weight if(a.validators_voted_for > 0){ share_type fair_delta = delta / a.validators_voted_for; modify(a, [&](account_object &acc) { acc.validators_vote_weight += fair_delta; }); - const auto &vidx = get_index().indices().get(); + const auto &vidx = get_index().indices().get(); auto itr = vidx.lower_bound(boost::make_tuple(a.id, validator_id_type())); while (itr != vidx.end() && itr->account == a.id) { - adjust_validator_vote(get(itr->witness), fair_delta); + adjust_validator_vote(get(itr->validator), fair_delta); ++itr; } } } else{ - const auto &vidx = get_index().indices().get(); + const auto &vidx = get_index().indices().get(); auto itr = vidx.lower_bound(boost::make_tuple(a.id, validator_id_type())); while (itr != vidx.end() && itr->account == a.id) { - adjust_validator_vote(get(itr->witness), delta); + adjust_validator_vote(get(itr->validator), delta); ++itr; } } } - void database::adjust_validator_vote(const validator_object &witness, share_type delta) { + void database::adjust_validator_vote(const validator_object &validator, share_type delta) { const validator_schedule_object &wso = get_validator_schedule_object(); - modify(witness, [&](validator_object &w) { + modify(validator, [&](validator_object &w) { auto delta_pos = w.counted_votes.value * (wso.current_virtual_time - w.virtual_last_update); w.virtual_position += delta_pos; @@ -3344,7 +3386,7 @@ namespace graphene { namespace chain { w.virtual_position) / (w.counted_votes.value + 1); - /** witnesses with a low number of votes could overflow the time field and end up with a scheduled time in the past */ + /** validators with a low number of votes could overflow the time field and end up with a scheduled time in the past */ if (w.virtual_scheduled_time < wso.current_virtual_time) { w.virtual_scheduled_time = fc::uint128_t::max_value(); } @@ -3352,7 +3394,7 @@ namespace graphene { namespace chain { } void database::clear_validator_votes(const account_object &a) { - const auto &vidx = get_index().indices().get(); + const auto &vidx = get_index().indices().get(); auto itr = vidx.lower_bound(boost::make_tuple(a.id, validator_id_type())); while (itr != vidx.end() && itr->account == a.id) { const auto ¤t = *itr; @@ -3362,7 +3404,7 @@ namespace graphene { namespace chain { modify(a, [&](account_object &acc) { acc.validators_voted_for = 0; - if(has_hardfork(CHAIN_HARDFORK_5)){//need to clear witness vote weight + if(has_hardfork(CHAIN_HARDFORK_5)){//need to clear validator vote weight acc.validators_vote_weight = 0; } }); @@ -3803,11 +3845,11 @@ namespace graphene { namespace chain { const auto &props = get_dynamic_global_properties(); if(has_hardfork(CHAIN_HARDFORK_11)){//new emission model (fixed amount of digital asset per block) share_type digital_asset_per_block = int64_t( CHAIN_DIGITAL_ASSET_ISSUED_PER_BLOCK ); - auto witness_reward = ( digital_asset_per_block * props.inflation_validator_percent ) / CHAIN_100_PERCENT; - auto ratio_reward = digital_asset_per_block - witness_reward; + auto validator_reward = ( digital_asset_per_block * props.inflation_validator_percent ) / CHAIN_100_PERCENT; + auto ratio_reward = digital_asset_per_block - validator_reward; auto committee_part = ( ratio_reward * props.inflation_ratio ) / CHAIN_100_PERCENT; auto reward_fund_part = ratio_reward - committee_part; - digital_asset_per_block = witness_reward + committee_part + reward_fund_part; + digital_asset_per_block = validator_reward + committee_part + reward_fund_part; modify( props, [&]( dynamic_global_property_object& p ) { p.committee_fund += asset( committee_part, TOKEN_SYMBOL ); @@ -3815,9 +3857,9 @@ namespace graphene { namespace chain { p.current_supply += asset( digital_asset_per_block, TOKEN_SYMBOL ); }); - const auto& cwit = get_witness( props.current_validator ); - const auto* witness_account = find_account(cwit.owner); - if (!witness_account) { + const auto& cwit = get_validator( props.current_validator ); + const auto* validator_account = find_account(cwit.owner); + if (!validator_account) { auto& acc_idx = get_index().indices().get(); elog("CRITICAL: Validator ${w} account object MISSING from database! " "This is impossible state - shared memory may be corrupted. " @@ -3831,16 +3873,16 @@ namespace graphene { namespace chain { ("w", cwit.owner)); } if (has_hardfork(CHAIN_HARDFORK_13) && cwit.sharing_rate > 0) { - // HF13: split witness_reward between validator and stakeholder pool (both in TOKEN). + // HF13: split validator_reward between validator and stakeholder pool (both in TOKEN). // Validator receives SHARES immediately via create_vesting. // Stakeholder portion is accumulated as TOKEN in pending_stakeholder_reward and // distributed to stakeholders via create_vesting at each epoch end. - share_type stakeholder_token = (fc::uint128_t(witness_reward.value) * + share_type stakeholder_token = (fc::uint128_t(validator_reward.value) * cwit.sharing_rate / CHAIN_100_PERCENT).to_uint64(); - share_type validator_token = witness_reward - stakeholder_token; + share_type validator_token = validator_reward - stakeholder_token; if (validator_token > 0) { - auto validator_vshares = create_vesting(*witness_account, asset(validator_token, TOKEN_SYMBOL)); + auto validator_vshares = create_vesting(*validator_account, asset(validator_token, TOKEN_SYMBOL)); push_virtual_operation(validator_reward_operation(cwit.owner, validator_vshares)); } @@ -3850,8 +3892,8 @@ namespace graphene { namespace chain { }); } } else { - auto witness_reward_shares = create_vesting(*witness_account, asset(witness_reward, TOKEN_SYMBOL)); - push_virtual_operation(validator_reward_operation(cwit.owner, witness_reward_shares)); + auto validator_reward_shares = create_vesting(*validator_account, asset(validator_reward, TOKEN_SYMBOL)); + push_virtual_operation(validator_reward_operation(cwit.owner, validator_reward_shares)); } } else{ @@ -3871,11 +3913,11 @@ namespace graphene { namespace chain { share_type inflation_per_block = inflation_per_year / int64_t( CHAIN_BLOCKS_PER_YEAR ); if(has_hardfork(CHAIN_HARDFORK_4)){//consensus inflation model - auto witness_reward = ( inflation_per_block * props.inflation_validator_percent ) / CHAIN_100_PERCENT; - auto inflation_ratio_reward = inflation_per_block - witness_reward; + auto validator_reward = ( inflation_per_block * props.inflation_validator_percent ) / CHAIN_100_PERCENT; + auto inflation_ratio_reward = inflation_per_block - validator_reward; auto committee_reward = ( inflation_ratio_reward * props.inflation_ratio ) / CHAIN_100_PERCENT; auto content_reward = inflation_ratio_reward - committee_reward; - inflation_per_block = witness_reward + committee_reward + content_reward; + inflation_per_block = validator_reward + committee_reward + content_reward; modify( props, [&]( dynamic_global_property_object& p ) { @@ -3884,9 +3926,9 @@ namespace graphene { namespace chain { p.current_supply += asset( inflation_per_block, TOKEN_SYMBOL ); }); - const auto& cwit = get_witness( props.current_validator ); - const auto* witness_account = find_account(cwit.owner); - if (!witness_account) { + const auto& cwit = get_validator( props.current_validator ); + const auto* validator_account = find_account(cwit.owner); + if (!validator_account) { auto& acc_idx = get_index().indices().get(); elog("CRITICAL: Validator ${w} account object MISSING from database (HF4 path)! " "This is impossible state - shared memory may be corrupted. " @@ -3899,8 +3941,8 @@ namespace graphene { namespace chain { "CRITICAL: Validator ${w} account not found in database (HF4 path)! Shared memory corruption suspected.", ("w", cwit.owner)); } - auto witness_reward_shares = create_vesting(*witness_account, asset(witness_reward, TOKEN_SYMBOL)); - push_virtual_operation(validator_reward_operation(cwit.owner,witness_reward_shares)); + auto validator_reward_shares = create_vesting(*validator_account, asset(validator_reward, TOKEN_SYMBOL)); + push_virtual_operation(validator_reward_operation(cwit.owner,validator_reward_shares)); } else{ /*ilog( "Inflation status: props.head_block_number=${h1}, inflation_per_year=${h2}, new_supply=${h3}, inflation_per_block=${h4}", @@ -3909,14 +3951,14 @@ namespace graphene { namespace chain { auto content_reward = ( inflation_per_block * CHAIN_REWARD_FUND_PERCENT ) / CHAIN_100_PERCENT; auto vesting_reward = ( inflation_per_block * CHAIN_VESTING_FUND_PERCENT ) / CHAIN_100_PERCENT; /// 15% to vesting fund auto committee_reward = ( inflation_per_block * CHAIN_COMMITTEE_FUND_PERCENT ) / CHAIN_100_PERCENT; - auto witness_reward = inflation_per_block - content_reward - vesting_reward - committee_reward; /// Remaining 10% to witness pay + auto validator_reward = inflation_per_block - content_reward - vesting_reward - committee_reward; /// Remaining 10% to validator pay - const auto& cwit = get_witness( props.current_validator ); + const auto& cwit = get_validator( props.current_validator ); - inflation_per_block = content_reward + vesting_reward + committee_reward + witness_reward; + inflation_per_block = content_reward + vesting_reward + committee_reward + validator_reward; /* - elog( "Final inflation_per_block=${h1}, content_reward=${h2}, committee_reward=${h3}, witness_reward=${h4}, vesting_reward=${h5}", - ("h1",inflation_per_block)("h2", content_reward)("h3",committee_reward)("h4",witness_reward)("h5",vesting_reward) + elog( "Final inflation_per_block=${h1}, content_reward=${h2}, committee_reward=${h3}, validator_reward=${h4}, vesting_reward=${h5}", + ("h1",inflation_per_block)("h2", content_reward)("h3",committee_reward)("h4",validator_reward)("h5",vesting_reward) ); */ modify( props, [&]( dynamic_global_property_object& p ) @@ -3927,8 +3969,8 @@ namespace graphene { namespace chain { p.current_supply += asset( inflation_per_block, TOKEN_SYMBOL ); }); - auto witness_reward_shares = create_vesting(get_account(cwit.owner), asset(witness_reward, TOKEN_SYMBOL)); - push_virtual_operation(validator_reward_operation(cwit.owner,witness_reward_shares)); + auto validator_reward_shares = create_vesting(get_account(cwit.owner), asset(validator_reward, TOKEN_SYMBOL)); + push_virtual_operation(validator_reward_operation(cwit.owner,validator_reward_shares)); } } } @@ -3945,14 +3987,14 @@ namespace graphene { namespace chain { // epoch_length is guaranteed >= CHAIN_MIN_DISTRIBUTION_EPOCH_LENGTH > 0. uint32_t epoch_start_block = head_block_num() - epoch_length + 1; - const auto& vote_idx = get_index().indices().get(); + const auto& vote_idx = get_index().indices().get(); const auto& widx = get_index().indices().get(); for (const auto& wit : widx) { if (wit.pending_stakeholder_reward == 0) continue; - const auto* witness_account = find_account(wit.owner); - if (!witness_account) continue; + const auto* validator_account = find_account(wit.owner); + if (!validator_account) continue; share_type total_token = wit.pending_stakeholder_reward; @@ -3970,7 +4012,7 @@ namespace graphene { namespace chain { std::vector entries; { auto itr = vote_idx.lower_bound(boost::make_tuple(wit.id, account_id_type())); - while (itr != vote_idx.end() && itr->witness == wit.id) { + while (itr != vote_idx.end() && itr->validator == wit.id) { const auto& stakeholder = get(itr->account); // Fair weight: total stake divided by number of validators voted for, // matching the actual per-validator weight used in consensus scheduling. @@ -3990,7 +4032,7 @@ namespace graphene { namespace chain { if (total_weighted == 0) { // No stakeholders — entire pool returns to validator. - auto dust_shares = create_vesting(*witness_account, asset(total_token, TOKEN_SYMBOL)); + auto dust_shares = create_vesting(*validator_account, asset(total_token, TOKEN_SYMBOL)); push_virtual_operation(validator_reward_operation(wit.owner, dust_shares)); modify(wit, [&](validator_object& w) { w.pending_stakeholder_reward = 0; }); continue; @@ -4014,7 +4056,7 @@ namespace graphene { namespace chain { // Remaining TOKEN (dust from rounding + sub-threshold shares) goes back to the validator. share_type dust_token = total_token - total_distributed_token; if (dust_token > 0) { - auto dust_shares = create_vesting(*witness_account, asset(dust_token, TOKEN_SYMBOL)); + auto dust_shares = create_vesting(*validator_account, asset(dust_token, TOKEN_SYMBOL)); push_virtual_operation(validator_reward_operation(wit.owner, dust_shares)); } @@ -4561,7 +4603,7 @@ namespace graphene { namespace chain { add_core_index(*this); add_core_index(*this); add_core_index(*this); - add_core_index(*this); + add_core_index(*this); add_core_index(*this); add_core_index(*this); add_core_index(*this); @@ -4580,7 +4622,7 @@ namespace graphene { namespace chain { add_core_index(*this); add_core_index(*this); add_core_index(*this); - add_core_index(*this); + add_core_index(*this); add_core_index(*this); _plugin_index_signal(); @@ -4791,7 +4833,7 @@ namespace graphene { namespace chain { hpo.processed_hardforks.push_back(genesis_time); }); - // Create witness scheduler + // Create validator scheduler create([&](validator_schedule_object &wso) { wso.current_shuffled_validators[0] = CHAIN_COMMITTEE_ACCOUNT; }); @@ -4806,9 +4848,9 @@ namespace graphene { namespace chain { FC_ASSERT( hardfork_state.current_hardfork_version == _hardfork_versions[n], "Unexpected genesis hardfork state" ); - const auto& witness_idx = get_index().indices().get(); + const auto& validator_idx = get_index().indices().get(); vector wit_ids_to_update; - for( auto it=witness_idx.begin(); it!=witness_idx.end(); ++it ) + for( auto it=validator_idx.begin(); it!=validator_idx.end(); ++it ) wit_ids_to_update.push_back(it->id); for( validator_id_type wit_id : wit_ids_to_update ) @@ -4822,9 +4864,9 @@ namespace graphene { namespace chain { } } else{ - const auto& witness_idx = get_index().indices().get(); + const auto& validator_idx = get_index().indices().get(); vector wit_ids_to_update; - for( auto it=witness_idx.begin(); it!=witness_idx.end(); ++it ) + for( auto it=validator_idx.begin(); it!=validator_idx.end(); ++it ) wit_ids_to_update.push_back(it->id); for( validator_id_type wit_id : wit_ids_to_update ) @@ -4945,8 +4987,8 @@ namespace graphene { namespace chain { } - public_key_type database::get_witness_key(const account_name_type& name) { - return get_witness(name).signing_key; + public_key_type database::get_validator_key(const account_name_type& name) { + return get_validator(name).signing_key; } void database::_validate_transaction(const signed_transaction &trx, uint32_t skip) { @@ -5063,7 +5105,7 @@ namespace graphene { namespace chain { | skip_authority_check /* | skip_merkle_check While blockchain is being downloaded, txs need to be validated against block headers */ | skip_undo_history_check - | skip_witness_schedule_check + | skip_validator_schedule_check | skip_validate_operations; } } @@ -5107,13 +5149,13 @@ namespace graphene { namespace chain { _validate_block(next_block, skip); - const validator_object &signing_witness = validate_block_header(skip, next_block); + const validator_object &signing_validator = validate_block_header(skip, next_block); _current_block_num = next_block_num; _current_trx_in_block = 0; _current_virtual_op = 0; - /// modify current witness so transaction evaluators can know who included the transaction, + /// modify current validator so transaction evaluators can know who included the transaction, /// this is mostly for POW operations which must pay the current_validator modify(gprops, [&](dynamic_global_property_object &dgp) { dgp.current_validator = next_block.validator; @@ -5130,13 +5172,13 @@ namespace graphene { namespace chain { }); } - /// parse witness version reporting + /// parse validator version reporting process_header_extensions(next_block); - const auto &witness = get_witness(next_block.validator); - FC_ASSERT(witness.running_version >= hardfork_state.current_hardfork_version, + const auto &validator = get_validator(next_block.validator); + FC_ASSERT(validator.running_version >= hardfork_state.current_hardfork_version, "Block produced by validator that is not running current hardfork", - ("validator", witness)("next_block.validator", next_block.validator)("hardfork_state", hardfork_state) + ("validator", validator)("next_block.validator", next_block.validator)("hardfork_state", hardfork_state) ); for (const auto &trx : next_block.transactions) { @@ -5155,7 +5197,7 @@ namespace graphene { namespace chain { _current_virtual_op = 0; update_global_dynamic_data(next_block, skip); - update_signing_witness(signing_witness, next_block); + update_signing_validator(signing_validator, next_block); update_last_irreversible_block(skip); @@ -5168,7 +5210,7 @@ namespace graphene { namespace chain { clear_closed_committee_requests(); } update_bandwidth_reserve_candidates(); - update_witness_schedule(); + update_validator_schedule(); if (_debug_block_production) ilog("DEBUG_CRASH: update_validator_schedule done"); if (_debug_block_production) ilog("DEBUG_CRASH: process_funds start"); @@ -5232,12 +5274,12 @@ namespace graphene { namespace chain { case 1: // version { auto reported_version = itr->get(); - const auto &signing_witness = get_witness(next_block.validator); - //idump( (next_block.validator)(signing_witness.running_version)(reported_version) ); + const auto &signing_validator = get_validator(next_block.validator); + //idump( (next_block.validator)(signing_validator.running_version)(reported_version) ); if (reported_version != - signing_witness.running_version) { - modify(signing_witness, [&](validator_object &wo) { + signing_validator.running_version) { + modify(signing_validator, [&](validator_object &wo) { wo.running_version = reported_version; }); } @@ -5246,13 +5288,13 @@ namespace graphene { namespace chain { case 2: // hardfork_version vote { auto hfv = itr->get(); - const auto &signing_witness = get_witness(next_block.validator); - //idump( (next_block.validator)(signing_witness.running_version)(hfv) ); + const auto &signing_validator = get_validator(next_block.validator); + //idump( (next_block.validator)(signing_validator.running_version)(hfv) ); if (hfv.hf_version != - signing_witness.hardfork_version_vote || - hfv.hf_time != signing_witness.hardfork_time_vote) { - modify(signing_witness, [&](validator_object &wo) { + signing_validator.hardfork_version_vote || + hfv.hf_time != signing_validator.hardfork_time_vote) { + modify(signing_validator, [&](validator_object &wo) { wo.hardfork_version_vote = hfv.hf_version; wo.hardfork_time_vote = hfv.hf_time; }); @@ -5346,60 +5388,60 @@ namespace graphene { namespace chain { next_block.previous, "", ("head_block_id", head_block_id())("next.prev", next_block.previous)); FC_ASSERT(head_block_time() < next_block.timestamp, "", ("head_block_time", head_block_time())("next", next_block.timestamp)("blocknum", next_block.block_num())); - const validator_object &witness = get_witness(next_block.validator); + const validator_object &validator = get_validator(next_block.validator); if (!(skip & skip_validator_signature)) { - FC_ASSERT(witness.signing_key != public_key_type(), + FC_ASSERT(validator.signing_key != public_key_type(), "Validator '${w}' has null signing key — cannot validate block #${n}. " "The validator disabled their key or the node is on a different fork.", ("w", next_block.validator)("n", next_block.block_num())); - FC_ASSERT(next_block.validate_signee(witness.signing_key)); + FC_ASSERT(next_block.validate_signee(validator.signing_key)); } - if (!(skip & skip_witness_schedule_check)) { + if (!(skip & skip_validator_schedule_check)) { uint32_t slot_num = get_slot_at_time(next_block.timestamp); FC_ASSERT(slot_num > 0); - string scheduled_witness = get_scheduled_validator(slot_num); + string scheduled_validator = get_scheduled_validator(slot_num); - // During emergency consensus, the witness schedule can diverge + // During emergency consensus, the validator schedule can diverge // between competing forks (different blocks → different shuffle). - // A block from another fork may have a different witness for the + // A block from another fork may have a different validator for the // same slot — that block is still valid, just from a different // chain view. Accept it: if a competing block from the - // "correct" witness arrives, fork_db picks the winner via + // "correct" validator arrives, fork_db picks the winner via // vote-weighted comparison. If no competition arrives, this // block IS the correct one. // - // We still validate the signature (the witness must hold the + // We still validate the signature (the validator must hold the // correct signing key) and all other block properties — we only - // relax the strict slot-to-witness mapping. + // relax the strict slot-to-validator mapping. const dynamic_global_property_object &dgp = get_dynamic_global_properties(); if (has_hardfork(CHAIN_HARDFORK_12) && dgp.emergency_consensus_active) { - if (witness.owner != scheduled_witness) { - // Relax strict slot-to-witness mapping, but still - // require the witness to be IN the current schedule. + if (validator.owner != scheduled_validator) { + // Relax strict slot-to-validator mapping, but still + // require the validator to be IN the current schedule. // This prevents arbitrary key holders from producing // blocks in random slots while allowing competing // forks with different shuffles to interoperate. const validator_schedule_object &wso = get_validator_schedule_object(); bool in_schedule = false; for (int i = 0; i < wso.num_scheduled_validators; i += CHAIN_BLOCK_VALIDATOR_REPEAT) { - if (wso.current_shuffled_validators[i] == witness.owner) { + if (wso.current_shuffled_validators[i] == validator.owner) { in_schedule = true; break; } } FC_ASSERT(in_schedule, "Emergency mode: block from validator ${w} not in current schedule", - ("w", witness.owner)); + ("w", validator.owner)); dlog("Emergency mode: accepting block from ${bw} at slot scheduled for ${sw} " "(slot_num=${slot}, block=#${num})", - ("bw", next_block.validator)("sw", scheduled_witness) + ("bw", next_block.validator)("sw", scheduled_validator) ("slot", slot_num)("num", next_block.block_num())); } } else { - if (witness.owner != scheduled_witness) { + if (validator.owner != scheduled_validator) { // Throw a typed exception so the caller can // distinguish a schedule mismatch from other // validation failures. Schedule mismatch is @@ -5408,12 +5450,12 @@ namespace graphene { namespace chain { // win via vote-weighted comparison. FC_THROW_EXCEPTION(wrong_scheduled_validator_exception, "Validator produced block at wrong time", - ("block validator", next_block.validator)("scheduled", scheduled_witness)("slot_num", slot_num)); + ("block validator", next_block.validator)("scheduled", scheduled_validator)("slot_num", slot_num)); } } } - return witness; + return validator; } FC_CAPTURE_AND_RETHROW() } @@ -5439,40 +5481,40 @@ namespace graphene { namespace chain { assert(missed_blocks != 0); missed_blocks--; for (uint32_t i = 0; i < missed_blocks; ++i) { - const auto &witness_missed = get_witness(get_scheduled_validator(i + 1)); + const auto &validator_missed = get_validator(get_scheduled_validator(i + 1)); - // During emergency mode, skip penalties for offline witnesses. + // During emergency mode, skip penalties for offline validators. // The hybrid schedule assigns committee to fill their slots, but // their slots still get counted as "missed" when committee produces. - // Without this guard, offline witnesses accumulate penalties and + // Without this guard, offline validators accumulate penalties and // eventually get signing_key=null (shutdown), which defeats the // purpose of emergency penalty reset and prevents recovery. - bool is_emergency_offline_witness = + bool is_emergency_offline_validator = has_hardfork(CHAIN_HARDFORK_12) && _dgp.emergency_consensus_active && - witness_missed.owner != b.validator && - witness_missed.owner != CHAIN_EMERGENCY_VALIDATOR_ACCOUNT; + validator_missed.owner != b.validator && + validator_missed.owner != CHAIN_EMERGENCY_VALIDATOR_ACCOUNT; - if (!is_emergency_offline_witness && witness_missed.owner != b.validator) { + if (!is_emergency_offline_validator && validator_missed.owner != b.validator) { ilog("\033[91mMissed block: validator ${w} did not produce block #${n} at ${t} (next: ${next})\033[0m", - ("w", witness_missed.owner) + ("w", validator_missed.owner) ("n", head_block_num() + i + 1) ("t", get_slot_time(i + 1)) ("next", b.validator)); } - modify(witness_missed, [&](validator_object &w) { - // Only reset current_run for witnesses that actually missed their slot. - // In emergency hybrid mode, the committee witness occupies multiple + modify(validator_missed, [&](validator_object &w) { + // Only reset current_run for validators that actually missed their slot. + // In emergency hybrid mode, the committee validator occupies multiple // schedule slots and produces the current block. If we reset current_run - // for the committee witness's duplicate slots (which are also "missed" + // for the committee validator's duplicate slots (which are also "missed" // because committee can't fill all slots simultaneously), current_run // never reaches CHAIN_IRREVERSIBLE_SUPPORT_MIN_RUN, so // last_supported_block_num never advances and LIB stalls. if (w.owner != b.validator) { w.current_run = 0; } - if(is_emergency_offline_witness) { + if(is_emergency_offline_validator) { // Emergency mode: skip per-block vote penalties and total_missed. // Key-blanking uses a deterministic consensus check: // head_block_num - last_confirmed_block_num (both on-chain state) @@ -5489,20 +5531,20 @@ namespace graphene { namespace chain { w.signing_key = public_key_type(); push_virtual_operation(shutdown_validator_operation(w.owner)); } - } else if(witness_missed.owner != b.validator){ - // total_missed does not increment when witness_missed.owner == b.validator - // because a low total_missed is a "prestige" item and a witness that + } else if(validator_missed.owner != b.validator){ + // total_missed does not increment when validator_missed.owner == b.validator + // because a low total_missed is a "prestige" item and a validator that // restarts a dead network is "rewarded" by not having total_missed // increase for any blocks they missed in the gap. // Also, this prevents initminer from having a large total_missed. w.total_missed++; - if(has_hardfork(CHAIN_HARDFORK_6)){// Consensus counted votes penalty to witness for block missing + if(has_hardfork(CHAIN_HARDFORK_6)){// Consensus counted votes penalty to validator for block missing w.penalty_percent+=consensus.median_props.validator_miss_penalty_percent; w.counted_votes=(fc::uint128_t(w.votes) - (fc::uint128_t(w.votes) * std::min(w.penalty_percent,uint32_t(CHAIN_100_PERCENT)) / CHAIN_100_PERCENT )).to_uint64(); - create([&](witness_penalty_expire_object& wpe) { - wpe.witness = witness_missed.owner; + create([&](validator_penalty_expire_object& wpe) { + wpe.validator = validator_missed.owner; wpe.penalty_percent = consensus.median_props.validator_miss_penalty_percent; wpe.expires = head_block_time() + fc::seconds(consensus.median_props.validator_miss_penalty_duration); }); @@ -5611,7 +5653,7 @@ namespace graphene { namespace chain { // to genesis_time would cause a false activation with // millions of seconds since LIB, immediately triggering // emergency mode and deadlocking the node (committee - // schedule doesn't match real witness slots, blocks from + // schedule doesn't match real validator slots, blocks from // p2p are rejected, head_block_num never advances, // next_shuffle_block_num never reached). @@ -5644,11 +5686,11 @@ namespace graphene { namespace chain { dgp.emergency_consensus_start_block = b.block_num(); }); - // Change 5: Ensure emergency witness object exists with correct key - const auto &witness_by_name = get_index().indices().get(); - auto wit_itr = witness_by_name.find(CHAIN_EMERGENCY_VALIDATOR_ACCOUNT); + // Change 5: Ensure emergency validator object exists with correct key + const auto &validator_by_name = get_index().indices().get(); + auto wit_itr = validator_by_name.find(CHAIN_EMERGENCY_VALIDATOR_ACCOUNT); - if (wit_itr == witness_by_name.end()) { + if (wit_itr == validator_by_name.end()) { create([&](validator_object &w) { w.owner = CHAIN_EMERGENCY_VALIDATOR_ACCOUNT; w.signing_key = CHAIN_EMERGENCY_VALIDATOR_PUBLIC_KEY; @@ -5664,8 +5706,8 @@ namespace graphene { namespace chain { w.hardfork_version_vote = hfp.current_hardfork_version; w.hardfork_time_vote = hfp.processed_hardforks[hfp.last_hardfork]; // Copy the current median chain properties so that the - // committee witness does not skew the median when it's - // counted in update_median_witness_props(). With median + // committee validator does not skew the median when it's + // counted in update_median_validator_props(). With median // props, N committee entries are invisible to the median // computation (they just reinforce the existing median). w.props = get_validator_schedule_object().median_props; @@ -5684,12 +5726,12 @@ namespace graphene { namespace chain { }); } - // Change 7: Disable all real witnesses and reset penalties. + // Change 7: Disable all real validators and reset penalties. // On emergency start, zero signing_key so ONLY committee produces. - // Operators must manually re-enable witnesses via update_witness tx. - const auto &witness_idx = get_index().indices().get(); + // Operators must manually re-enable validators via update_validator tx. + const auto &validator_idx = get_index().indices().get(); uint32_t blanked_count = 0; - for (auto witr = witness_idx.begin(); witr != witness_idx.end(); ++witr) { + for (auto witr = validator_idx.begin(); witr != validator_idx.end(); ++witr) { if (witr->owner == CHAIN_EMERGENCY_VALIDATOR_ACCOUNT) continue; if (witr->signing_key != public_key_type()) blanked_count++; modify(*witr, [&](validator_object &w) { @@ -5704,7 +5746,7 @@ namespace graphene { namespace chain { ("n", blanked_count)); // Remove all pending penalty expiration objects - const auto &penalty_idx = get_index().indices().get(); + const auto &penalty_idx = get_index().indices().get(); auto pen_itr = penalty_idx.begin(); while (pen_itr != penalty_idx.end()) { const auto ¤t = *pen_itr; @@ -5712,12 +5754,12 @@ namespace graphene { namespace chain { remove(current); } - // Override witness schedule: all slots -> emergency witness + // Override validator schedule: all slots -> emergency validator // Also update next_shuffle_block_num so the hybrid override // runs on the next schedule update. Without this, if // next_shuffle_block_num is still N blocks away, the node // would run an all-committee schedule until then, rejecting - // blocks from real witnesses during that window. + // blocks from real validators during that window. const validator_schedule_object &wso = get_validator_schedule_object(); modify(wso, [&](validator_schedule_object &_wso) { for (int i = 0; i < _wso.num_scheduled_validators; i++) { @@ -5742,7 +5784,7 @@ namespace graphene { namespace chain { } //after block is applied check block post validation chain step by step - //if count of validation is more than 2/3 of witnesses, then update last irreversible block num + //if count of validation is more than 2/3 of validators, then update last irreversible block num void database::check_block_post_validation_chain(){ try { // Don't advance LIB via post-validation chain during emergency mode @@ -5919,10 +5961,10 @@ namespace graphene { namespace chain { } FC_CAPTURE_AND_RETHROW() } - //p2p plugin check witness signature on handle_message - //and apply block post validation for block id by witness account - //if count of validation is more than 2/3 of witnesses, then update last irreversible block num - void database::apply_block_post_validation(block_id_type block_id, const account_name_type &witness_account){ + //p2p plugin check validator signature on handle_message + //and apply block post validation for block id by validator account + //if count of validation is more than 2/3 of validators, then update last irreversible block num + void database::apply_block_post_validation(block_id_type block_id, const account_name_type &validator_account){ try { // Don't advance LIB via post-validation during emergency mode const dynamic_global_property_object &emergency_dpo = get_dynamic_global_properties(); @@ -5930,14 +5972,14 @@ namespace graphene { namespace chain { return; } - // Reject post-validations from witnesses not in the current schedule. - // Only scheduled witnesses can contribute to LIB advancement; accepting - // validations from non-scheduled witnesses is pointless and could be + // Reject post-validations from validators not in the current schedule. + // Only scheduled validators can contribute to LIB advancement; accepting + // validations from non-scheduled validators is pointless and could be // exploited for spam. const validator_schedule_object &wso = get_validator_schedule_object(); bool is_scheduled = false; for (int i = 0; i < wso.num_scheduled_validators; i += CHAIN_BLOCK_VALIDATOR_REPEAT) { - if (wso.current_shuffled_validators[i] == witness_account) { + if (wso.current_shuffled_validators[i] == validator_account) { is_scheduled = true; break; } @@ -5959,9 +6001,9 @@ namespace graphene { namespace chain { if(current.block_id == block_id){ find_block_num = current.block_num; modify(current, [&](validator_confirmation_object &o) { - //remove witness from shuffled witnesses + //remove validator from shuffled validators for (size_t j = 0; j< CHAIN_MAX_VALIDATORS; j++) { - if(o.current_shuffled_validators[j] == witness_account){ + if(o.current_shuffled_validators[j] == validator_account){ o.current_shuffled_validators_validations[j] = true; //need update find = true; @@ -6123,9 +6165,9 @@ namespace graphene { namespace chain { } FC_CAPTURE_AND_RETHROW() } - //get block post validation objects for witness + //get block post validation objects for validator //return array of validator_confirmation_object event if it is empty - std::array database::get_validator_confirmations(const account_name_type &witness_account){ + std::array database::get_validator_confirmations(const account_name_type &validator_account){ std::array result; const auto& validation_list = get_index().indices().get(); auto itr = validation_list.begin(); @@ -6134,11 +6176,11 @@ namespace graphene { namespace chain { { const auto& current = *itr; ++itr; - //if witness is in the list add it to result + //if validator is in the list add it to result //only count the first match per validation object (committee can occupy multiple slots) bool matched = false; for (size_t j = 0; j < CHAIN_MAX_VALIDATORS && !matched; j++) { - if(current.current_shuffled_validators[j] == witness_account){ + if(current.current_shuffled_validators[j] == validator_account){ if(current.current_shuffled_validators_validations[j] == false){//need validate result[i] = validator_confirmation_object(current); ++i; @@ -6154,10 +6196,10 @@ namespace graphene { namespace chain { return result; } - //create block post validation object with current shuffled witnesses + //create block post validation object with current shuffled validators //remove old block post validation objects //remove old blocks from post validation list if it is full (CHAIN_MAX_BLOCK_POST_VALIDATION_COUNT) - void database::create_block_post_validation(uint32_t block_num, block_id_type block_id, const account_name_type& witness_account){ + void database::create_block_post_validation(uint32_t block_num, block_id_type block_id, const account_name_type& validator_account){ const dynamic_global_property_object &dpo = get_dynamic_global_properties(); //remove blocks if they height is less than last irreversible block const auto& validation_list = get_index().indices().get(); @@ -6192,7 +6234,7 @@ namespace graphene { namespace chain { size_t validator_index=0; size_t i = 0; for (; i < wso.num_scheduled_validators; i+=CHAIN_BLOCK_VALIDATOR_REPEAT) { - if(witness_account != wso.current_shuffled_validators[i]){ + if(validator_account != wso.current_shuffled_validators[i]){ o.current_shuffled_validators[validator_index] = account_name_type(wso.current_shuffled_validators[i]); o.current_shuffled_validators_validations[validator_index] = false; validator_index++; @@ -6205,13 +6247,13 @@ namespace graphene { namespace chain { }); } - void database::update_signing_witness(const validator_object &signing_witness, const signed_block &new_block) { + void database::update_signing_validator(const validator_object &signing_validator, const signed_block &new_block) { try { const dynamic_global_property_object &dpo = get_dynamic_global_properties(); uint64_t new_block_aslot = dpo.current_aslot + get_slot_at_time(new_block.timestamp); - modify(signing_witness, [&](validator_object &_wit) { + modify(signing_validator, [&](validator_object &_wit) { _wit.last_aslot = new_block_aslot; _wit.last_confirmed_block_num = new_block.block_num(); if( _wit.current_run >= CHAIN_IRREVERSIBLE_SUPPORT_MIN_RUN ){ @@ -6228,20 +6270,20 @@ namespace graphene { namespace chain { const validator_schedule_object &wso = get_validator_schedule_object(); // === HARDFORK 12: EMERGENCY LIB === - // During emergency mode, LIB advances normally using all witnesses + // During emergency mode, LIB advances normally using all validators // in the schedule (including committee). Committee produces every // block, so after current_run >= CHAIN_IRREVERSIBLE_SUPPORT_MIN_RUN // (3 blocks), LIB advances every block (capped at HEAD-1 to preserve // undo protection — see cap below). This keeps the gap between // LIB and head small, preventing fork_db overflow on long emergencies. - // When operators re-enable real witnesses and emergency exits, + // When operators re-enable real validators and emergency exits, // normal LIB computation continues seamlessly. // === END HARDFORK 12 EMERGENCY LIB === vector wit_objs; wit_objs.reserve(wso.num_scheduled_validators); for (int i = 0; i < wso.num_scheduled_validators; i+=CHAIN_BLOCK_VALIDATOR_REPEAT) { - wit_objs.push_back(&get_witness(wso.current_shuffled_validators[i])); + wit_objs.push_back(&get_validator(wso.current_shuffled_validators[i])); } static_assert(CHAIN_IRREVERSIBLE_THRESHOLD > @@ -6266,10 +6308,10 @@ namespace graphene { namespace chain { // === HARDFORK 12: EMERGENCY LIB CAP === // During emergency, all schedule slots point to the same committee - // witness, so nth_element yields last_supported_block_num == HEAD. + // validator, so nth_element yields last_supported_block_num == HEAD. // If we commit(HEAD), the undo session for the CURRENT block is // destroyed. Any subsequent modify() in _apply_block (e.g. - // update_witness_schedule) becomes permanent with NO rollback. + // update_validator_schedule) becomes permanent with NO rollback. // A crash after commit but before _apply_block finishes leaves // permanently corrupted state (e.g. zeroed schedule). // Cap LIB to HEAD-1 so the current block always has undo protection. @@ -6602,8 +6644,8 @@ namespace graphene { namespace chain { }); const auto &idx = get_index().indices(); - for (const auto &witness : idx) { - modify(witness, [&](validator_object &wobj) { + for (const auto &validator : idx) { + modify(validator, [&](validator_object &wobj) { wobj.virtual_position = fc::uint128_t(); wobj.virtual_last_update = wso.current_virtual_time; wobj.virtual_scheduled_time = VIRTUAL_SCHEDULE_LAP_LENGTH2 / @@ -6753,21 +6795,21 @@ namespace graphene { namespace chain { p.total_reward_shares=0; }); - //recalc witness votes for fair DPOS - const auto &widx = get_index().indices(); + //recalc validator votes for fair DPOS + const auto &widx = get_index().indices(); for(auto witr = widx.begin(); witr != widx.end(); ++witr) { const auto &voter = get(witr->account); share_type old_weight=voter.validator_vote_weight(); share_type new_weight=voter.validator_vote_fair_weight_prehf5(); - adjust_validator_vote(get(witr->witness), -old_weight); - adjust_validator_vote(get(witr->witness), new_weight); + adjust_validator_vote(get(witr->validator), -old_weight); + adjust_validator_vote(get(witr->validator), new_weight); } break; } case CHAIN_HARDFORK_5: { - //clear votes for each witness + //clear votes for each validator const auto &widx = get_index().indices().get(); for (auto itr = widx.begin(); itr != widx.end(); @@ -6778,19 +6820,19 @@ namespace graphene { namespace chain { w.counted_votes = 0; }); } - //recalc witness votes for fair DPOS - const auto &widx2 = get_index().indices(); + //recalc validator votes for fair DPOS + const auto &widx2 = get_index().indices(); for(auto witr = widx2.begin(); witr != widx2.end(); ++witr) { const auto &voter = get(witr->account); - const auto &witness = get(witr->witness); + const auto &validator = get(witr->validator); share_type fair_weight=voter.validator_vote_fair_weight(); modify(voter, [&](account_object &a) { a.validators_vote_weight = fair_weight; }); - elog("HF5 validator ${a} calc votes: ${n}", ("a", witness.owner)("n", fair_weight)); + elog("HF5 validator ${a} calc votes: ${n}", ("a", validator.owner)("n", fair_weight)); - adjust_validator_vote(get(witr->witness), fair_weight); + adjust_validator_vote(get(witr->validator), fair_weight); } break; } @@ -6919,7 +6961,7 @@ namespace graphene { namespace chain { }); } - //clear votes for each witness + //clear votes for each validator const auto &widx = get_index().indices().get(); for (auto itr = widx.begin(); itr != widx.end(); @@ -6930,19 +6972,19 @@ namespace graphene { namespace chain { w.counted_votes = 0; }); } - //recalc witness votes after shares ratio fix - const auto &widx2 = get_index().indices(); + //recalc validator votes after shares ratio fix + const auto &widx2 = get_index().indices(); for(auto witr = widx2.begin(); witr != widx2.end(); ++witr) { const auto &voter = get(witr->account); - const auto &witness = get(witr->witness); + const auto &validator = get(witr->validator); share_type fair_weight=voter.validator_vote_fair_weight(); modify(voter, [&](account_object &a) { a.validators_vote_weight = fair_weight; }); - elog("HF6 validator ${a} recalc votes from ${a}: ${n}", ("a", witness.owner)("n", fair_weight)); + elog("HF6 validator ${a} recalc votes from ${a}: ${n}", ("a", validator.owner)("n", fair_weight)); - adjust_validator_vote(get(witr->witness), fair_weight); + adjust_validator_vote(get(witr->validator), fair_weight); } break; } @@ -7089,20 +7131,20 @@ namespace graphene { namespace chain { } //decrease validators_vote_weight from all votes by invalid account - const auto &vidx = get_index().indices().get(); + const auto &vidx = get_index().indices().get(); auto vitr = vidx.lower_bound(boost::make_tuple(current.id, validator_id_type())); while (vitr != vidx.end() && vitr->account == current.id) { - adjust_validator_vote(get(vitr->witness),-current.validators_vote_weight); + adjust_validator_vote(get(vitr->validator),-current.validators_vote_weight); ++vitr; } - //remove from witness_vote_index by_account_witness (remove all votes from invalid account) - const auto &d10idx = get_index().indices().get(); + //remove from validator_vote_index by_account_validator (remove all votes from invalid account) + const auto &d10idx = get_index().indices().get(); auto delete_itr10 = d10idx.lower_bound(boost::make_tuple(current.id, validator_id_type())); while(delete_itr10 != d10idx.end() && delete_itr10->account == current.id) { const auto &delete_current = *delete_itr10; - adjust_validator_vote(get(delete_itr10->witness),-current.validators_vote_weight); + adjust_validator_vote(get(delete_itr10->validator),-current.validators_vote_weight); modify(current, [&](account_object &a) { a.validators_voted_for--; }); @@ -7110,42 +7152,42 @@ namespace graphene { namespace chain { remove(delete_current); } - //recalc validators_vote_weight (must be 0 after remove all witness votes from invalid account) + //recalc validators_vote_weight (must be 0 after remove all validator votes from invalid account) share_type current_fair_vote_weight = current.validator_vote_fair_weight(); modify(current, [&](account_object &a) { a.validators_vote_weight = current_fair_vote_weight; }); - //look witness object from invalid account - const auto &invalid_witness = find(current.name); - if(invalid_witness != nullptr){//found witness - //remove invalid witness account from penalty index - const auto &d8idx = get_index().indices().get(); - auto delete_itr8 = d8idx.lower_bound(invalid_witness->owner); + //look validator object from invalid account + const auto &invalid_validator = find(current.name); + if(invalid_validator != nullptr){//found validator + //remove invalid validator account from penalty index + const auto &d8idx = get_index().indices().get(); + auto delete_itr8 = d8idx.lower_bound(invalid_validator->owner); while(delete_itr8 != d8idx.end() && - delete_itr8->witness == invalid_witness->owner) { + delete_itr8->validator == invalid_validator->owner) { const auto &delete_current = *delete_itr8; ++delete_itr8; remove(delete_current); } - //remove invalid witness account from schedule + //remove invalid validator account from schedule const validator_schedule_object &wso = get_validator_schedule_object(); modify(wso, [&](validator_schedule_object &_wso) { for (int i = 0; i < _wso.num_scheduled_validators; i+=CHAIN_BLOCK_VALIDATOR_REPEAT) { - if(_wso.current_shuffled_validators[i] == invalid_witness->owner){ + if(_wso.current_shuffled_validators[i] == invalid_validator->owner){ _wso.current_shuffled_validators[i] = account_name_type(); } } }); - //recalc validators_vote_weight from all votes to invalid witness account (remove votes to invalid witness account) - const auto &vidx = get_index().indices().get(); - auto vitr = vidx.lower_bound(boost::make_tuple(invalid_witness->id, account_id_type())); - while (vitr != vidx.end() && vitr->witness == invalid_witness->id) { + //recalc validators_vote_weight from all votes to invalid validator account (remove votes to invalid validator account) + const auto &vidx = get_index().indices().get(); + auto vitr = vidx.lower_bound(boost::make_tuple(invalid_validator->id, account_id_type())); + while (vitr != vidx.end() && vitr->validator == invalid_validator->id) { const auto &voter_account = get(vitr->account); - const auto &vidx2 = get_index().indices().get(); + const auto &vidx2 = get_index().indices().get(); auto vitr2 = vidx2.lower_bound(boost::make_tuple(voter_account.id, validator_id_type())); while (vitr2 != vidx2.end() && vitr2->account == voter_account.id) { - adjust_validator_vote(get(vitr2->witness), -voter_account.validators_vote_weight); + adjust_validator_vote(get(vitr2->validator), -voter_account.validators_vote_weight); ++vitr2; } @@ -7160,16 +7202,16 @@ namespace graphene { namespace chain { a.validators_vote_weight = fair_vote_weight; }); - const auto &vidx3 = get_index().indices().get(); + const auto &vidx3 = get_index().indices().get(); auto vitr3 = vidx3.lower_bound(boost::make_tuple(voter_account.id, validator_id_type())); while (vitr3 != vidx3.end() && vitr3->account == voter_account.id) { - adjust_validator_vote(get(vitr3->witness), voter_account.validators_vote_weight); + adjust_validator_vote(get(vitr3->validator), voter_account.validators_vote_weight); ++vitr3; } ++vitr; } - //remove from validator_index invalid witness account + //remove from validator_index invalid validator account const auto &d9idx = get_index().indices().get(); auto delete_itr9 = d9idx.lower_bound(current.name); while(delete_itr9 != d9idx.end() && @@ -7385,32 +7427,32 @@ namespace graphene { namespace chain { } case CHAIN_HARDFORK_9: { - //remove witnesses without signed block + //remove validators without signed block const auto &idx = get_index().indices().get(); auto itr = idx.begin(); while(itr != idx.end()){ const auto ¤t = *itr; ++itr; if(0==current.last_confirmed_block_num){ - //MUST be corrected: the witness_vote_object must also be deleted - //remove invalid witness account from penalty index - const auto &d8idx = get_index().indices().get(); + //MUST be corrected: the validator_vote_object must also be deleted + //remove invalid validator account from penalty index + const auto &d8idx = get_index().indices().get(); auto delete_itr8 = d8idx.lower_bound(current.owner); while(delete_itr8 != d8idx.end() && - delete_itr8->witness == current.owner) { + delete_itr8->validator == current.owner) { const auto &delete_current = *delete_itr8; ++delete_itr8; remove(delete_current); } - //recalc validators_vote_weight from all votes to invalid witness account (remove votes to invalid witness account) - const auto &vidx = get_index().indices().get(); + //recalc validators_vote_weight from all votes to invalid validator account (remove votes to invalid validator account) + const auto &vidx = get_index().indices().get(); auto vitr = vidx.lower_bound(boost::make_tuple(current.id, account_id_type())); - while (vitr != vidx.end() && vitr->witness == current.id) { + while (vitr != vidx.end() && vitr->validator == current.id) { const auto &voter_account = get(vitr->account); - const auto &vidx2 = get_index().indices().get(); + const auto &vidx2 = get_index().indices().get(); auto vitr2 = vidx2.lower_bound(boost::make_tuple(voter_account.id, validator_id_type())); while (vitr2 != vidx2.end() && vitr2->account == voter_account.id) { - adjust_validator_vote(get(vitr2->witness), -voter_account.validators_vote_weight); + adjust_validator_vote(get(vitr2->validator), -voter_account.validators_vote_weight); ++vitr2; } @@ -7426,10 +7468,10 @@ namespace graphene { namespace chain { a.validators_vote_weight = fair_vote_weight; }); - const auto &vidx3 = get_index().indices().get(); + const auto &vidx3 = get_index().indices().get(); auto vitr3 = vidx3.lower_bound(boost::make_tuple(voter_account.id, validator_id_type())); while (vitr3 != vidx3.end() && vitr3->account == voter_account.id) { - adjust_validator_vote(get(vitr3->witness), voter_account.validators_vote_weight); + adjust_validator_vote(get(vitr3->validator), voter_account.validators_vote_weight); ++vitr3; } ++vitr; diff --git a/libraries/chain/hardfork.d/5.hf b/libraries/chain/hardfork.d/5.hf index 311b68275c..96024b7302 100644 --- a/libraries/chain/hardfork.d/5.hf +++ b/libraries/chain/hardfork.d/5.hf @@ -1,4 +1,4 @@ -// 5 Hardfork on VIZ mainnet, fix witnesses votes +// 5 Hardfork on VIZ mainnet, fix validators votes #ifndef CHAIN_HARDFORK_5 #define CHAIN_HARDFORK_5 5 #define CHAIN_HARDFORK_5_TIME 1550656800 // 20 Feb 2019 10:00:00 GMT diff --git a/libraries/chain/include/graphene/chain/chain_object_types.hpp b/libraries/chain/include/graphene/chain/chain_object_types.hpp index a4393c879b..a58b48fc44 100644 --- a/libraries/chain/include/graphene/chain/chain_object_types.hpp +++ b/libraries/chain/include/graphene/chain/chain_object_types.hpp @@ -52,7 +52,7 @@ namespace graphene { namespace chain { content_object_type, content_type_object_type, content_vote_object_type, - witness_vote_object_type, + validator_vote_object_type, hardfork_property_object_type, withdraw_vesting_route_object_type, master_authority_history_object_type, @@ -72,7 +72,7 @@ namespace graphene { namespace chain { award_shares_expire_object_type, paid_subscription_object_type, paid_subscribe_object_type, - witness_penalty_expire_object_type, + validator_penalty_expire_object_type, validator_confirmation_object_type }; @@ -88,7 +88,7 @@ namespace graphene { namespace chain { class content_object; class content_type_object; class content_vote_object; - class witness_vote_object; + class validator_vote_object; class hardfork_property_object; class withdraw_vesting_route_object; class master_authority_history_object; @@ -107,7 +107,7 @@ namespace graphene { namespace chain { class award_shares_expire_object; class paid_subscription_object; class paid_subscribe_object; - class witness_penalty_expire_object; + class validator_penalty_expire_object; class validator_confirmation_object; typedef object_id dynamic_global_property_id_type; @@ -120,7 +120,7 @@ namespace graphene { namespace chain { typedef object_id content_id_type; typedef object_id content_type_id_type; typedef object_id content_vote_id_type; - typedef object_id witness_vote_id_type; + typedef object_id validator_vote_id_type; typedef object_id hardfork_property_id_type; typedef object_id withdraw_vesting_route_id_type; typedef object_id master_authority_history_id_type; @@ -140,7 +140,7 @@ namespace graphene { namespace chain { typedef object_id award_shares_expire_object_id_type; typedef object_id paid_subscription_object_id_type; typedef object_id paid_subscribe_object_id_type; - typedef object_id witness_penalty_expire_object_id_type; + typedef object_id validator_penalty_expire_object_id_type; typedef object_id validator_confirmation_object_id_type; } } //graphene::chain @@ -217,7 +217,7 @@ FC_REFLECT_ENUM(graphene::chain::object_type, (content_object_type) (content_type_object_type) (content_vote_object_type) - (witness_vote_object_type) + (validator_vote_object_type) (hardfork_property_object_type) (withdraw_vesting_route_object_type) (master_authority_history_object_type) @@ -237,7 +237,7 @@ FC_REFLECT_ENUM(graphene::chain::object_type, (award_shares_expire_object_type) (paid_subscription_object_type) (paid_subscribe_object_type) - (witness_penalty_expire_object_type) + (validator_penalty_expire_object_type) (validator_confirmation_object_type) ) diff --git a/libraries/chain/include/graphene/chain/database.hpp b/libraries/chain/include/graphene/chain/database.hpp index e9e3cd59af..ae58e89bd8 100644 --- a/libraries/chain/include/graphene/chain/database.hpp +++ b/libraries/chain/include/graphene/chain/database.hpp @@ -100,7 +100,7 @@ namespace graphene { namespace chain { enum validation_steps { skip_nothing = 0, skip_validator_signature = 1 << 0, ///< used while reindexing - skip_transaction_signatures = 1 << 1, ///< used by non-witness nodes + skip_transaction_signatures = 1 << 1, ///< used by non-validator nodes skip_transaction_dupe_check = 1 << 2, ///< used while reindexing skip_fork_db = 1 << 3, ///< used while reindexing skip_block_size_check = 1 << 4, ///< used when applying locally generated transactions @@ -108,7 +108,7 @@ namespace graphene { namespace chain { skip_authority_check = 1 << 6, ///< used while reindexing -- disables any checking of authority on transactions skip_merkle_check = 1 << 7, ///< used while reindexing skip_undo_history_check = 1 << 8, ///< used while reindexing - skip_witness_schedule_check = 1 << 9, ///< used while reindexing + skip_validator_schedule_check = 1 << 9, ///< used while reindexing skip_validate_operations = 1 << 10, ///< used prior to checkpoint, skips validate() call on transaction skip_undo_block = 1 << 11, ///< used to skip undo db on reindex skip_block_log = 1 << 12, ///< used to skip block logging on reindex @@ -221,9 +221,9 @@ namespace graphene { namespace chain { chain_id_type get_chain_id() const; - const validator_object &get_witness(const account_name_type &name) const; + const validator_object &get_validator(const account_name_type &name) const; - const validator_object *find_witness(const account_name_type &name) const; + const validator_object *find_validator(const account_name_type &name) const; const account_object &get_account(const account_name_type &name) const; @@ -269,7 +269,7 @@ namespace graphene { namespace chain { * Calculate the percent of block production slots that were missed in the * past 128 blocks, not including the current block. */ - uint32_t witness_participation_rate() const; + uint32_t validator_participation_rate() const; void add_checkpoints(const flat_map &checkpts); @@ -301,14 +301,14 @@ namespace graphene { namespace chain { signed_block generate_block( const fc::time_point_sec when, - const account_name_type &witness_owner, + const account_name_type &validator_owner, const fc::ecc::private_key &block_signing_private_key, uint32_t skip ); signed_block _generate_block( const fc::time_point_sec when, - const account_name_type &witness_owner, + const account_name_type &validator_owner, const fc::ecc::private_key &block_signing_private_key, uint32_t skip ); @@ -381,15 +381,15 @@ namespace graphene { namespace chain { */ //fc::signal&)> removed_objects; - //////////////////// db_witness_schedule.cpp //////////////////// + //////////////////// db_validator_schedule.cpp //////////////////// /** - * @brief Get the witness scheduled for block production in a slot. + * @brief Get the validator scheduled for block production in a slot. * * slot_num always corresponds to a time in the future. * - * If slot_num == 1, returns the next scheduled witness. - * If slot_num == 2, returns the next scheduled witness after + * If slot_num == 1, returns the next scheduled validator. + * If slot_num == 2, returns the next scheduled validator after * 1 block gap. * * Use the get_slot_time() and get_slot_at_time() functions @@ -427,7 +427,7 @@ namespace graphene { namespace chain { void update_bandwidth_reserve_candidates(); - void update_witness_schedule(); + void update_validator_schedule(); void adjust_balance(const account_object &a, const asset &delta); @@ -443,23 +443,23 @@ namespace graphene { namespace chain { return get_balance(get_account(aname), symbol); } - /** this updates the votes for witnesses as a result of account voting proxy changing */ + /** this updates the votes for validators as a result of account voting proxy changing */ void adjust_proxied_validator_votes(const account_object &a, const std::array &delta, int depth = 0); - /** this updates the votes for all witnesses as a result of account SHARES changing */ + /** this updates the votes for all validators as a result of account SHARES changing */ void adjust_proxied_validator_votes(const account_object &a, share_type delta, int depth = 0); /** this is called by `adjust_proxied_validator_votes` when account proxy to self */ void adjust_validator_votes(const account_object &a, share_type delta); - /** this updates the vote of a single witness as a result of a vote being added or removed*/ + /** this updates the vote of a single validator as a result of a vote being added or removed*/ void adjust_validator_vote(const validator_object &obj, share_type delta); /** clears all vote records for a particular account but does not update the - * witness vote totals. Vote totals should be updated first via a call to + * validator vote totals. Vote totals should be updated first via a call to * adjust_proxied_validator_votes( a, -a.validator_vote_weight() ) */ void clear_validator_votes(const account_object &a); @@ -560,22 +560,22 @@ namespace graphene { namespace chain { return _fork_db; } - public_key_type get_witness_key(const account_name_type &name); + public_key_type get_validator_key(const account_name_type &name); - void create_block_post_validation(uint32_t block_num, block_id_type block_id, const account_name_type &witness_account); + void create_block_post_validation(uint32_t block_num, block_id_type block_id, const account_name_type &validator_account); - std::array get_validator_confirmations(const account_name_type &witness_account); + std::array get_validator_confirmations(const account_name_type &validator_account); - void apply_block_post_validation(block_id_type block_id, const account_name_type &witness_account); + void apply_block_post_validation(block_id_type block_id, const account_name_type &validator_account); void check_block_post_validation_chain(); /** * Compare two fork branches by vote weight (HF12 logic). - * Sums wit_obj.votes (on-chain stake) for all unique witnesses in each branch, + * Sums wit_obj.votes (on-chain stake) for all unique validators in each branch, * from the tip back to the common ancestor. * The longer chain gets a +10% bonus on its total weight (reflects that more - * witnesses kept producing on it by consensus rules without deferring). + * validators kept producing on it by consensus rules without deferring). * @return >0 if branch_a is heavier, <0 if branch_b is heavier, 0 if tied * @return 0 if either tip is not in fork_db (cannot compare) */ @@ -611,7 +611,7 @@ namespace graphene { namespace chain { void create_block_summary(const signed_block &next_block); - void update_median_witness_props(); + void update_median_validator_props(); void clear_null_account_balance(); @@ -621,7 +621,7 @@ namespace graphene { namespace chain { void update_global_dynamic_data(const signed_block &b, uint32_t skip); - void update_signing_witness(const validator_object &signing_witness, const signed_block &new_block); + void update_signing_validator(const validator_object &signing_validator, const signed_block &new_block); void update_last_irreversible_block(uint32_t skip); diff --git a/libraries/chain/include/graphene/chain/global_property_object.hpp b/libraries/chain/include/graphene/chain/global_property_object.hpp index 7ca627570b..dba1c7cb88 100644 --- a/libraries/chain/include/graphene/chain/global_property_object.hpp +++ b/libraries/chain/include/graphene/chain/global_property_object.hpp @@ -72,12 +72,12 @@ namespace graphene { uint32_t average_block_size = 0; /** - * Maximum block size is decided by the set of active witnesses which change every round. - * Each witness posts what they think the maximum size should be as part of their witness + * Maximum block size is decided by the set of active validators which change every round. + * Each validator posts what they think the maximum size should be as part of their validator * properties, the median size is chosen to be the maximum block size for the round. * * @note the minimum value for maximum_block_size is defined by the protocol to prevent the - * network from getting stuck by witnesses attempting to set this too low. + * network from getting stuck by validators attempting to set this too low. */ uint32_t maximum_block_size = 0; @@ -127,7 +127,7 @@ namespace graphene { uint32_t vote_regeneration_per_day = CHAIN_VOTE_ENERGY_RATE; /** - * The number of accounts who can use bandwidth reserve assigned by witnesses consensus + * The number of accounts who can use bandwidth reserve assigned by validators consensus */ uint32_t bandwidth_reserve_candidates = 1; diff --git a/libraries/chain/include/graphene/chain/validator_objects.hpp b/libraries/chain/include/graphene/chain/validator_objects.hpp index df9349e86f..2d8d0a362f 100644 --- a/libraries/chain/include/graphene/chain/validator_objects.hpp +++ b/libraries/chain/include/graphene/chain/validator_objects.hpp @@ -20,7 +20,7 @@ namespace graphene { namespace chain { using chain_properties = graphene::protocol::chain_properties_hf13; /** - * All witnesses with at least 1% net positive approval and + * All validators with at least 1% net positive approval and * at least 2 weeks old are able to participate in block * production. */ @@ -43,7 +43,7 @@ namespace graphene { namespace chain { id_type id; - /** the account that has authority over this witness */ + /** the account that has authority over this validator */ account_name_type owner; time_point_sec created; shared_string url; @@ -56,36 +56,36 @@ namespace graphene { namespace chain { uint64_t last_supported_block_num = 0; /** - * This is the key used to sign blocks on behalf of this witness + * This is the key used to sign blocks on behalf of this validator */ public_key_type signing_key; chain_properties props; /** - * The total votes for this witness. This determines how the witness is ranked for - * scheduling. The top N witnesses by votes are scheduled every round, every one + * The total votes for this validator. This determines how the validator is ranked for + * scheduling. The top N validators by votes are scheduled every round, every one * else takes turns being scheduled proportional to their votes. */ share_type votes; uint32_t penalty_percent = 0; share_type counted_votes; - validator_schedule_type schedule = none; /// How the witness was scheduled the last time it was scheduled + validator_schedule_type schedule = none; /// How the validator was scheduled the last time it was scheduled /** - * These fields are used for the witness scheduling algorithm which uses - * virtual time to ensure that all witnesses are given proportional time + * These fields are used for the validator scheduling algorithm which uses + * virtual time to ensure that all validators are given proportional time * for producing blocks. * * @ref votes is used to determine speed. The @ref virtual_scheduled_time is - * the expected time at which this witness should complete a virtual lap which + * the expected time at which this validator should complete a virtual lap which * is defined as the position equal to 1000 times MAXVOTES. * * virtual_scheduled_time = virtual_last_update + (1000*MAXVOTES - virtual_position) / votes * * Every time the number of votes changes the virtual_position and virtual_scheduled_time must * update. There is a global current virtual_scheduled_time which gets updated every time - * a witness is scheduled. To update the virtual_position the following math is performed. + * a validator is scheduled. To update the virtual_position the following math is performed. * * virtual_position = virtual_position + votes * (virtual_current_time - virtual_last_update) * virtual_last_update = virtual_current_time @@ -107,7 +107,7 @@ namespace graphene { namespace chain { uint16_t sharing_rate = 0; /// Accumulated TOKEN (VIZ) pending distribution to stakeholders at epoch end. /// Stored in TOKEN atomic units; converted to SHARES via create_vesting() at epoch end. - /// witness_reward_operation for the validator carries only the validator's own share. + /// validator_reward_operation for the validator carries only the validator's own share. share_type pending_stakeholder_reward = 0; class validator_schedule_object : public object { @@ -131,7 +131,7 @@ namespace graphene { namespace chain { }; /** - * This field represents the blockchain version the witness is running. + * This field represents the blockchain version the validator is running. */ version running_version; @@ -140,20 +140,20 @@ namespace graphene { namespace chain { }; - class witness_vote_object - : public object { + class validator_vote_object + : public object { public: template - witness_vote_object(Constructor &&c, allocator a) { + validator_vote_object(Constructor &&c, allocator a) { c(*this); } - witness_vote_object() { + validator_vote_object() { } id_type id; - validator_id_type witness; + validator_id_type validator; account_id_type account; /// Block number when this vote was cast. Used by HF13 time-weighted epoch distribution. /// Zero for votes cast before HF13 (treated as epoch start = full weight). @@ -229,34 +229,34 @@ namespace graphene { namespace chain { member>>>, allocator>; - struct by_account_witness; - struct by_witness_account; + struct by_account_validator; + struct by_validator_account; - using witness_vote_index = multi_index_container < - witness_vote_object, + using validator_vote_index = multi_index_container < + validator_vote_object, indexed_by< ordered_unique< tag, - member>, + member>, ordered_unique< - tag, + tag, composite_key< - witness_vote_object, - member, - member>, + validator_vote_object, + member, + member>, composite_key_compare< std::less, std::less>>, ordered_unique< - tag, + tag, composite_key< - witness_vote_object, - member, - member>, + validator_vote_object, + member, + member>, composite_key_compare< std::less, std::less>>>, - allocator>; + allocator>; using validator_schedule_index = multi_index_container < validator_schedule_object, @@ -266,40 +266,40 @@ namespace graphene { namespace chain { member>>, allocator >; - class witness_penalty_expire_object - : public object { + class validator_penalty_expire_object + : public object { public: template - witness_penalty_expire_object(Constructor &&c, allocator a) { + validator_penalty_expire_object(Constructor &&c, allocator a) { c(*this); } - witness_penalty_expire_object() { + validator_penalty_expire_object() { } id_type id; - account_name_type witness; + account_name_type validator; int16_t penalty_percent; time_point_sec expires; }; struct by_expiration; struct by_account; typedef multi_index_container < - witness_penalty_expire_object, + validator_penalty_expire_object, indexed_by< ordered_unique, - member< witness_penalty_expire_object, witness_penalty_expire_object_id_type, & witness_penalty_expire_object::id> + member< validator_penalty_expire_object, validator_penalty_expire_object_id_type, & validator_penalty_expire_object::id> >, ordered_non_unique, - member< witness_penalty_expire_object, account_name_type, & witness_penalty_expire_object::witness> + member< validator_penalty_expire_object, account_name_type, & validator_penalty_expire_object::validator> >, ordered_non_unique, - member< witness_penalty_expire_object, time_point_sec, & witness_penalty_expire_object::expires> + member< validator_penalty_expire_object, time_point_sec, & validator_penalty_expire_object::expires> > >, - allocator < witness_penalty_expire_object> + allocator < validator_penalty_expire_object> > - witness_penalty_expire_index; + validator_penalty_expire_index; } } @@ -314,13 +314,13 @@ FC_REFLECT( CHAINBASE_SET_INDEX_TYPE(graphene::chain::validator_object, graphene::chain::validator_index) -FC_REFLECT((graphene::chain::witness_vote_object), (id)(witness)(account)(vote_created_block)) -CHAINBASE_SET_INDEX_TYPE(graphene::chain::witness_vote_object, graphene::chain::witness_vote_index) +FC_REFLECT((graphene::chain::validator_vote_object), (id)(validator)(account)(vote_created_block)) +CHAINBASE_SET_INDEX_TYPE(graphene::chain::validator_vote_object, graphene::chain::validator_vote_index) FC_REFLECT((graphene::chain::validator_schedule_object), (id)(current_virtual_time)(next_shuffle_block_num)(current_shuffled_validators)(num_scheduled_validators) (median_props)(majority_version) ) CHAINBASE_SET_INDEX_TYPE(graphene::chain::validator_schedule_object, graphene::chain::validator_schedule_index) -FC_REFLECT((graphene::chain::witness_penalty_expire_object),(id)(witness)(penalty_percent)(expires)) -CHAINBASE_SET_INDEX_TYPE(graphene::chain::witness_penalty_expire_object, graphene::chain::witness_penalty_expire_index) \ No newline at end of file +FC_REFLECT((graphene::chain::validator_penalty_expire_object),(id)(validator)(penalty_percent)(expires)) +CHAINBASE_SET_INDEX_TYPE(graphene::chain::validator_penalty_expire_object, graphene::chain::validator_penalty_expire_index) \ No newline at end of file diff --git a/libraries/network/dlt_p2p_node.cpp b/libraries/network/dlt_p2p_node.cpp index 24faf9aaea..766dc495aa 100644 --- a/libraries/network/dlt_p2p_node.cpp +++ b/libraries/network/dlt_p2p_node.cpp @@ -1045,7 +1045,7 @@ void dlt_p2p_node::request_blocks_from_peer(peer_id peer) { } // P49 fix: Start from our_head (not our_head+1) so the peer's version - // of our head block is fetched. If two witnesses signed different blocks + // of our head block is fetched. If two validators signed different blocks // at the same height, the peer may have the competing version. Without // this, the sync range skips the divergence point and blocks from the // competing fork accumulate as unlinkable in fork_db forever. @@ -1054,7 +1054,7 @@ void dlt_p2p_node::request_blocks_from_peer(peer_id peer) { // // LIB fallback: When significantly behind a peer (gap > threshold), // start from LIB instead of head. If our head diverged from the - // network (e.g. our witness produced blocks the network rejected), + // network (e.g. our validator produced blocks the network rejected), // requesting from head only gets ALREADY_KNOWN for head, then all // subsequent blocks go to fork_db as unlinkable. LIB is guaranteed // on the majority fork, giving the chain a chance to switch forks. @@ -2406,7 +2406,7 @@ void dlt_p2p_node::transition_to_forward() { // Clear chain's currently_syncing flag so the witness plugin can produce. // call_accept_block(sync_mode=true) during SYNC sets currently_syncing=true; // it only self-clears when the next accept_block(sync_mode=false) runs. - // If our witnesses are the only producers and they're blocked by + // If our validators are the only producers and they're blocked by // is_syncing()→not_synced, no FORWARD block ever arrives to clear it — // indefinite deadlock. Must clear here on every SYNC→FORWARD transition. if (_delegate) _delegate->clear_syncing(); diff --git a/libraries/network/include/graphene/network/dlt_p2p_node.hpp b/libraries/network/include/graphene/network/dlt_p2p_node.hpp index 4a17ddd9a3..02ed289789 100644 --- a/libraries/network/include/graphene/network/dlt_p2p_node.hpp +++ b/libraries/network/include/graphene/network/dlt_p2p_node.hpp @@ -84,7 +84,7 @@ class dlt_p2p_delegate { // currently_syncing flag is cleared. P2P sets currently_syncing=true // via call_accept_block(sync_mode=true) during bulk sync; without this // call the flag stays true after sync ends until the next FORWARD-mode - // block arrives. If our witnesses are the only remaining producers and + // block arrives. If our validators are the only remaining producers and // are themselves blocked by is_syncing()→not_synced, that arrival never // happens — causing indefinite silent production deadlock (p72: 570 s gap). virtual void clear_syncing() = 0; diff --git a/libraries/protocol/include/graphene/protocol/chain_operations.hpp b/libraries/protocol/include/graphene/protocol/chain_operations.hpp index cefd8da403..c638b2766b 100644 --- a/libraries/protocol/include/graphene/protocol/chain_operations.hpp +++ b/libraries/protocol/include/graphene/protocol/chain_operations.hpp @@ -349,8 +349,8 @@ namespace graphene { namespace protocol { struct chain_properties_hf13; /** - * Witnesses must vote on how to set certain chain properties to ensure a smooth - * and well functioning network. Any time @owner is in the active set of witnesses these + * Validators must vote on how to set certain chain properties to ensure a smooth + * and well functioning network. Any time @owner is in the active set of validators these * properties will be used to control the blockchain configuration. */ struct chain_properties_init { @@ -363,7 +363,7 @@ namespace graphene { namespace protocol { asset account_creation_fee = asset(CHAIN_MIN_ACCOUNT_CREATION_FEE, TOKEN_SYMBOL); /** - * This witnesses vote for the maximum_block_size which is used by the network + * This validators vote for the maximum_block_size which is used by the network * to tune rate limiting and capacity */ uint32_t maximum_block_size = CHAIN_MIN_BLOCK_SIZE_LIMIT * 2; @@ -444,7 +444,7 @@ namespace graphene { namespace protocol { struct chain_properties_hf4: public chain_properties_init { /** - * Consensus - Witness reward percent from block inflation + * Consensus - Validator reward percent from block inflation */ int16_t inflation_validator_percent = CHAIN_CONSENSUS_INFLATION_VALIDATOR_PERCENT; @@ -483,12 +483,12 @@ namespace graphene { namespace protocol { uint32_t data_operations_cost_additional_bandwidth = CONSENSUS_DATA_OPERATIONS_COST_ADDITIONAL_BANDWIDTH; /** - * Consensus - Witness who missed the block will receive a penality of a percentage of the votes + * Consensus - Validator who missed the block will receive a penality of a percentage of the votes */ int16_t validator_miss_penalty_percent = CONSENSUS_VALIDATOR_MISS_PENALTY_PERCENT; /** - * Consensus - Witness who missed the block will receive a penality with duration (in seconds) + * Consensus - Validator who missed the block will receive a penality with duration (in seconds) */ uint32_t validator_miss_penalty_duration = CONSENSUS_VALIDATOR_MISS_PENALTY_DURATION; @@ -541,7 +541,7 @@ namespace graphene { namespace protocol { asset subaccount_on_sale_fee = asset(CONSENSUS_SUBACCOUNT_ON_SALE_FEE, TOKEN_SYMBOL); /** - * Consensus - Fee to the network committee for declare account as witness + * Consensus - Fee to the network committee for declare account as validator */ asset validator_declaration_fee = asset(CONSENSUS_VALIDATOR_DECLARATION_FEE, TOKEN_SYMBOL); @@ -700,11 +700,11 @@ namespace graphene { namespace protocol { >; /** - * If the owner isn't a witness they will become a witness. + * If the owner isn't a validator they will become a validator. * - * If the block_signing_key is null then the witness is removed from - * contention. The network will pick the top 21 witnesses for - * producing blocks. + * If the block_signing_key is null then the validator is removed from + * contention. The network will pick the top 21 validators for + * validate blocks. */ struct validator_update_operation : public base_operation { account_name_type owner; @@ -748,7 +748,7 @@ namespace graphene { namespace protocol { /** - * All accounts with a VFS can vote for or against any witness. + * All accounts with a VFS can vote for or against any validator. * * If a proxy is specified then all existing votes are removed. */ @@ -911,11 +911,11 @@ namespace graphene { namespace protocol { * On account creation the recovery account is set either to the creator of * the account (The account that pays the creation fee and is a signer on the transaction) * or to the empty string if the account was in snapshot. An account with no recovery - * has the top voted witness as a recovery account, at the time the recover + * has the top voted validator as a recovery account, at the time the recover * request is created. Note: This does mean the effective recovery account * of an account with no listed recovery account can change at any time as - * witness vote weights. The top voted witness is explicitly the most trusted - * witness according to stake. + * validator vote weights. The top voted validator is explicitly the most trusted + * validator according to stake. */ struct change_recovery_account_operation : public base_operation { account_name_type account_to_recover; ///< The account that would be recovered in case of compromise diff --git a/libraries/protocol/include/graphene/protocol/config.hpp b/libraries/protocol/include/graphene/protocol/config.hpp index dd0a1a9ed8..5f0413866d 100644 --- a/libraries/protocol/include/graphene/protocol/config.hpp +++ b/libraries/protocol/include/graphene/protocol/config.hpp @@ -40,7 +40,7 @@ #define CHAIN_MAX_TOP_VALIDATORS 11 #define CHAIN_MAX_SUPPORT_VALIDATORS 10 #define CHAIN_MAX_VALIDATORS (CHAIN_MAX_TOP_VALIDATORS+CHAIN_MAX_SUPPORT_VALIDATORS) /// 21 is more than enough -#define CHAIN_HARDFORK_REQUIRED_VALIDATORS 17 // 17 of the 20 dpos witnesses (19 elected and 1 virtual time) required for hardfork. This guarantees 75% participation on all subsequent rounds. +#define CHAIN_HARDFORK_REQUIRED_VALIDATORS 17 // 17 of the 21 dpos validators required for hardfork. This guarantees 75% participation on all subsequent rounds. #define CHAIN_MAX_BLOCK_POST_VALIDATION_COUNT 20 #define CHAIN_MAX_TIME_UNTIL_EXPIRATION (60*60) // seconds, aka: 1 hour #define CHAIN_MAX_PROXY_RECURSION_DEPTH 4 @@ -120,8 +120,8 @@ #define CHAIN_EMERGENCY_VALIDATOR_PUBLIC_KEY (graphene::protocol::public_key_type(CHAIN_EMERGENCY_VALIDATOR_PUBLIC_KEY_STR)) /// Number of consecutive blocks produced by the emergency witness that -/// triggers automatic exit from emergency mode (witnesses have rejoined). -#define CHAIN_EMERGENCY_EXIT_NORMAL_BLOCKS 21 // 1 full round of 21 witnesses +/// triggers automatic exit from emergency mode (validators have rejoined). +#define CHAIN_EMERGENCY_EXIT_NORMAL_BLOCKS 21 // 1 full round of 21 validators #define CHAIN_IRREVERSIBLE_THRESHOLD (75 * CHAIN_1_PERCENT) /** Irreversibility only counts blocks produced if wit.current_run >= CHAIN_IRREVERSIBLE_SUPPORT_MIN_RUN */ diff --git a/libraries/protocol/include/graphene/protocol/config_testnet.hpp b/libraries/protocol/include/graphene/protocol/config_testnet.hpp index a56805b578..ee7e51fef8 100644 --- a/libraries/protocol/include/graphene/protocol/config_testnet.hpp +++ b/libraries/protocol/include/graphene/protocol/config_testnet.hpp @@ -120,8 +120,8 @@ #define CHAIN_EMERGENCY_VALIDATOR_PUBLIC_KEY (graphene::protocol::public_key_type(CHAIN_EMERGENCY_VALIDATOR_PUBLIC_KEY_STR)) /// Number of consecutive blocks produced by the emergency witness that -/// triggers automatic exit from emergency mode (witnesses have rejoined). -#define CHAIN_EMERGENCY_EXIT_NORMAL_BLOCKS 21 // 1 full round of 21 witnesses +/// triggers automatic exit from emergency mode (validators have rejoined). +#define CHAIN_EMERGENCY_EXIT_NORMAL_BLOCKS 21 // 1 full round of 21 validators #define CHAIN_IRREVERSIBLE_THRESHOLD (75 * CHAIN_1_PERCENT) /** Irreversibility only counts blocks produced if wit.current_run >= CHAIN_IRREVERSIBLE_SUPPORT_MIN_RUN */ diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index 76e2850cd2..2118c1a6df 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -255,7 +255,7 @@ namespace graphene { namespace wallet { vector get_ops_in_block( uint32_t block_num, bool only_virtual = true ); /** - * Returns the list of witnesses producing blocks in the current round (21 Blocks) + * Returns the list of validators producing blocks in the current round (21 Blocks) */ vector< account_name_type > get_active_validators()const; @@ -605,9 +605,9 @@ namespace graphene { namespace wallet { */ transaction_id_type get_transaction_id( const signed_transaction& trx )const { return trx.id(); } - /** Lists all witnesses registered in the blockchain. - * This returns a list of all account names that own witnesses, and the associated witness id, - * sorted by name. This lists witnesses whether they are currently voted in or not. + /** Lists all validators registered in the blockchain. + * This returns a list of all account names that own validators, and the associated witness id, + * sorted by name. This lists validators whether they are currently voted in or not. * * Use the \c lowerbound and limit parameters to page through the list. To retrieve all witnesss, * start by setting \c lowerbound to the empty string \c "", and then each iteration, pass diff --git a/plugins/custom_protocol_api/custom_protocol_api.cpp b/plugins/custom_protocol_api/custom_protocol_api.cpp index 5d1605910e..693a305e9f 100644 --- a/plugins/custom_protocol_api/custom_protocol_api.cpp +++ b/plugins/custom_protocol_api/custom_protocol_api.cpp @@ -117,7 +117,7 @@ namespace graphene { namespace plugins { namespace custom_protocol_api { auto& db = pimpl->database(); return db.with_weak_read_lock([&]() { const auto &idx = db.get_index().indices().get(); - const auto &vidx = db.get_index().indices().get(); + const auto &vidx = db.get_index().indices().get(); account_api_object result; auto itr = idx.find(account); @@ -126,7 +126,7 @@ namespace graphene { namespace plugins { namespace custom_protocol_api { auto vitr = vidx.lower_bound(boost::make_tuple(itr->id, validator_id_type())); while (vitr != vidx.end() && vitr->account == itr->id) { - result.validator_votes.insert(db.get(vitr->witness).owner); + result.validator_votes.insert(db.get(vitr->validator).owner); ++vitr; } diff --git a/plugins/database_api/api.cpp b/plugins/database_api/api.cpp index bc349a9b99..cecf8dc128 100755 --- a/plugins/database_api/api.cpp +++ b/plugins/database_api/api.cpp @@ -376,7 +376,7 @@ DEFINE_API(plugin, get_accounts) { std::vector plugin::api_impl::get_accounts(std::vector names) const { const auto &idx = _db.get_index().indices().get(); - const auto &vidx = _db.get_index().indices().get(); + const auto &vidx = _db.get_index().indices().get(); std::vector results; for (auto name: names) { @@ -385,7 +385,7 @@ std::vector plugin::api_impl::get_accounts(std::vectorid, validator_id_type())); while (vitr != vidx.end() && vitr->account == itr->id) { - results.back().validator_votes.insert(_db.get(vitr->witness).owner); + results.back().validator_votes.insert(_db.get(vitr->validator).owner); ++vitr; } } diff --git a/plugins/database_api/include/graphene/plugins/database_api/forward.hpp b/plugins/database_api/include/graphene/plugins/database_api/forward.hpp index 384d2e7f8a..211da2e67a 100644 --- a/plugins/database_api/include/graphene/plugins/database_api/forward.hpp +++ b/plugins/database_api/include/graphene/plugins/database_api/forward.hpp @@ -11,7 +11,7 @@ namespace graphene { namespace plugins { namespace database_api { typedef graphene::chain::dynamic_global_property_object dynamic_global_property_api_object; typedef graphene::chain::escrow_object escrow_api_object; typedef graphene::chain::withdraw_vesting_route_object withdraw_vesting_route_api_object; - typedef graphene::chain::witness_vote_object witness_vote_api_object; + typedef graphene::chain::validator_vote_object validator_vote_api_object; typedef graphene::chain::validator_schedule_object witness_schedule_api_object; using vesting_delegation_api_object = graphene::chain::vesting_delegation_object; diff --git a/plugins/snapshot/plugin.cpp b/plugins/snapshot/plugin.cpp index d448664759..f89b3dc81b 100644 --- a/plugins/snapshot/plugin.cpp +++ b/plugins/snapshot/plugin.cpp @@ -252,7 +252,7 @@ inline uint32_t import_account_authorities( return count; } -inline uint32_t import_witnesses( +inline uint32_t import_validators( graphene::chain::database& db, const fc::variants& arr ) { @@ -387,18 +387,22 @@ inline uint32_t import_content_votes( return count; } -inline uint32_t import_witness_votes( +inline uint32_t import_validator_votes( graphene::chain::database& db, const fc::variants& arr ) { uint32_t count = 0; for (const auto& v : arr) { auto id_val = v["id"].as_int64(); - auto& mutable_idx = db.get_mutable_index(); - mutable_idx.set_next_id(witness_vote_id_type(id_val)); - - db.create([&](witness_vote_object& obj) { - obj.witness = v["witness"].as(); + auto& mutable_idx = db.get_mutable_index(); + mutable_idx.set_next_id(validator_vote_id_type(id_val)); + + db.create([&](validator_vote_object& obj) { + // backward compat: old snapshots used "witness" field name + if (v.get_object().contains("validator")) + obj.validator = v["validator"].as(); + else if (v.get_object().contains("witness")) + obj.validator = v["witness"].as(); obj.account = v["account"].as(); // HF13: flash-voter protection (default 0 for pre-HF13 snapshots) if (v.get_object().contains("vote_created_block")) @@ -409,7 +413,7 @@ inline uint32_t import_witness_votes( return count; } -inline uint32_t import_witness_schedule( +inline uint32_t import_validator_schedule( graphene::chain::database& db, const fc::variants& arr ) { @@ -552,6 +556,33 @@ uint32_t import_simple_objects( return count; } +/// Import validator_penalty_expire objects with backward compat for old +/// "witness" field name inside the object (pre-rename snapshots). +inline uint32_t import_validator_penalty_expire( + graphene::chain::database& db, + const fc::variants& arr +) { + uint32_t count = 0; + for (const auto& v : arr) { + auto id_val = v["id"].as_int64(); + auto& mutable_idx = db.get_mutable_index(); + mutable_idx.set_next_id(validator_penalty_expire_object::id_type(id_val)); + + db.create([&](validator_penalty_expire_object& obj) { + // backward compat: old snapshots used "witness" field name + if (v.get_object().contains("validator")) { + obj.validator = v["validator"].as(); + } else if (v.get_object().contains("witness")) { + obj.validator = v["witness"].as(); + } + obj.penalty_percent = static_cast(v["penalty_percent"].as_int64()); + obj.expires = v["expires"].as(); + }); + ++count; + } + return count; +} + // Objects with shared_string: committee_request, invite, paid_subscription, proposal inline uint32_t import_committee_requests( graphene::chain::database& db, @@ -763,7 +794,7 @@ class snapshot_plugin::plugin_impl { std::string snapshot_dir; // --snapshot-dir: directory for auto-generated snapshots uint32_t snapshot_max_age_days = 90; // --snapshot-max-age-days: delete snapshots older than N days (0 = disabled) - // Deferred snapshot creation (to avoid interrupting witness block production) + // Deferred snapshot creation (to avoid interrupting validator block production) bool snapshot_pending = false; // deferred snapshot flag std::string pending_snapshot_path; // path for deferred snapshot fc::time_point_sec pending_snapshot_safe_after_time; // earliest head_block_time safe to start deferred snapshot @@ -938,12 +969,12 @@ fc::mutable_variant_object snapshot_plugin::plugin_impl::serialize_state() { // CRITICAL objects EXPORT_INDEX(dynamic_global_property_index, dynamic_global_property_object, "dynamic_global_property") - EXPORT_INDEX(validator_schedule_index, validator_schedule_object, "witness_schedule") + EXPORT_INDEX(validator_schedule_index, validator_schedule_object, "validator_schedule") EXPORT_INDEX(hardfork_property_index, hardfork_property_object, "hardfork_property") EXPORT_INDEX(account_index, account_object, "account") EXPORT_INDEX(account_authority_index, account_authority_object, "account_authority") - EXPORT_INDEX(validator_index, validator_object, "witness") - EXPORT_INDEX(witness_vote_index, witness_vote_object, "witness_vote") + EXPORT_INDEX(validator_index, validator_object, "validator") + EXPORT_INDEX(validator_vote_index, validator_vote_object, "validator_vote") EXPORT_INDEX(block_summary_index, block_summary_object, "block_summary") EXPORT_INDEX(content_index, content_object, "content") EXPORT_INDEX(content_vote_index, content_vote_object, "content_vote") @@ -965,7 +996,7 @@ fc::mutable_variant_object snapshot_plugin::plugin_impl::serialize_state() { // snapshot time and is included in that block will trigger // "Duplicate transaction check failed". // - // The witness node needs this index to avoid producing blocks with + // The validator node needs this index to avoid producing blocks with // duplicate transactions, so we must export confirmed entries. { fc::flat_set pending_ids; @@ -1064,7 +1095,7 @@ fc::mutable_variant_object snapshot_plugin::plugin_impl::serialize_state() { EXPORT_INDEX(award_shares_expire_index, award_shares_expire_object, "award_shares_expire") EXPORT_INDEX(paid_subscription_index, paid_subscription_object, "paid_subscription") EXPORT_INDEX(paid_subscribe_index, paid_subscribe_object, "paid_subscribe") - EXPORT_INDEX(witness_penalty_expire_index, witness_penalty_expire_object, "witness_penalty_expire") + EXPORT_INDEX(validator_penalty_expire_index, validator_penalty_expire_object, "validator_penalty_expire") // OPTIONAL objects EXPORT_INDEX(content_type_index, content_type_object, "content_type") @@ -1397,8 +1428,8 @@ void snapshot_plugin::plugin_impl::load_snapshot(const fc::path& input_path) { // For initial load (fresh DB from open_from_snapshot), these indexes // are empty and the loops are no-ops. // - // init_genesis() creates initial accounts, authorities, witnesses, and metadata - // that would conflict with the snapshot's objects. Singletons (dgp, witness_schedule, + // init_genesis() creates initial accounts, authorities, validators, and metadata + // that would conflict with the snapshot's objects. Singletons (dgp, validator_schedule, // hardfork_property) and block_summaries are handled separately (modify-in-place). { ilog(CLOG_ORANGE "Clearing existing objects before snapshot import..." CLOG_RESET); @@ -1417,7 +1448,7 @@ void snapshot_plugin::plugin_impl::load_snapshot(const fc::path& input_path) { // Also clear all other multi-instance object types that may exist // from a previous snapshot (hot-reload path). These are no-ops on // a fresh database. - const auto& wv_idx = db.get_index().indices(); + const auto& wv_idx = db.get_index().indices(); while (!wv_idx.empty()) { db.remove(*wv_idx.begin()); } const auto& bs_idx = db.get_index().indices(); @@ -1474,7 +1505,7 @@ void snapshot_plugin::plugin_impl::load_snapshot(const fc::path& input_path) { const auto& psb_idx = db.get_index().indices(); while (!psb_idx.empty()) { db.remove(*psb_idx.begin()); } - const auto& wpe_idx = db.get_index().indices(); + const auto& wpe_idx = db.get_index().indices(); while (!wpe_idx.empty()) { db.remove(*wpe_idx.begin()); } const auto& ct_idx = db.get_index().indices(); @@ -1496,9 +1527,13 @@ void snapshot_plugin::plugin_impl::load_snapshot(const fc::path& input_path) { detail::import_dynamic_global_properties(db, state["dynamic_global_property"].get_array()); ilog(CLOG_ORANGE "Imported dynamic_global_property" CLOG_RESET); } - if (state.contains("witness_schedule")) { - detail::import_witness_schedule(db, state["witness_schedule"].get_array()); - ilog(CLOG_ORANGE "Imported witness_schedule" CLOG_RESET); + if (state.contains("validator_schedule")) { + detail::import_validator_schedule(db, state["validator_schedule"].get_array()); + ilog(CLOG_ORANGE "Imported validator_schedule" CLOG_RESET); + } else if (state.contains("witness_schedule")) { + // backward compat: old snapshots used "witness_schedule" key + detail::import_validator_schedule(db, state["witness_schedule"].get_array()); + ilog(CLOG_ORANGE "Imported validator_schedule (from witness_schedule)" CLOG_RESET); } if (state.contains("hardfork_property")) { detail::import_hardfork_property(db, state["hardfork_property"].get_array()); @@ -1514,13 +1549,21 @@ void snapshot_plugin::plugin_impl::load_snapshot(const fc::path& input_path) { auto n = detail::import_account_authorities(db, state["account_authority"].get_array()); ilog(CLOG_ORANGE "Imported ${n} account authorities" CLOG_RESET, ("n", n)); } - if (state.contains("witness")) { - auto n = detail::import_witnesses(db, state["witness"].get_array()); - ilog(CLOG_ORANGE "Imported ${n} witnesses" CLOG_RESET, ("n", n)); + if (state.contains("validator")) { + auto n = detail::import_validators(db, state["validator"].get_array()); + ilog(CLOG_ORANGE "Imported ${n} validators" CLOG_RESET, ("n", n)); + } else if (state.contains("witness")) { + // backward compat: old snapshots used "witness" key + auto n = detail::import_validators(db, state["witness"].get_array()); + ilog(CLOG_ORANGE "Imported ${n} validators (from witness)" CLOG_RESET, ("n", n)); } - if (state.contains("witness_vote")) { - auto n = detail::import_witness_votes(db, state["witness_vote"].get_array()); - ilog(CLOG_ORANGE "Imported ${n} witness votes" CLOG_RESET, ("n", n)); + if (state.contains("validator_vote")) { + auto n = detail::import_validator_votes(db, state["validator_vote"].get_array()); + ilog(CLOG_ORANGE "Imported ${n} validator votes" CLOG_RESET, ("n", n)); + } else if (state.contains("witness_vote")) { + // backward compat: old snapshots used "witness_vote" key + auto n = detail::import_validator_votes(db, state["witness_vote"].get_array()); + ilog(CLOG_ORANGE "Imported ${n} validator votes (from witness_vote)" CLOG_RESET, ("n", n)); } if (state.contains("block_summary")) { auto n = detail::import_block_summaries(db, state["block_summary"].get_array()); @@ -1596,9 +1639,13 @@ void snapshot_plugin::plugin_impl::load_snapshot(const fc::path& input_path) { auto n = detail::import_simple_objects(db, state["paid_subscribe"].get_array()); ilog(CLOG_ORANGE "Imported ${n} paid subscribes" CLOG_RESET, ("n", n)); } - if (state.contains("witness_penalty_expire")) { - auto n = detail::import_simple_objects(db, state["witness_penalty_expire"].get_array()); - ilog(CLOG_ORANGE "Imported ${n} witness penalty expire objects" CLOG_RESET, ("n", n)); + if (state.contains("validator_penalty_expire")) { + auto n = detail::import_validator_penalty_expire(db, state["validator_penalty_expire"].get_array()); + ilog(CLOG_ORANGE "Imported ${n} validator penalty expire objects" CLOG_RESET, ("n", n)); + } else if (state.contains("witness_penalty_expire")) { + // backward compat: old snapshots used "witness_penalty_expire" key + auto n = detail::import_validator_penalty_expire(db, state["witness_penalty_expire"].get_array()); + ilog(CLOG_ORANGE "Imported ${n} validator penalty expire objects (from witness_penalty_expire)" CLOG_RESET, ("n", n)); } // OPTIONAL objects @@ -1623,6 +1670,34 @@ void snapshot_plugin::plugin_impl::load_snapshot(const fc::path& input_path) { ilog(CLOG_ORANGE "Imported ${n} change recovery account requests" CLOG_RESET, ("n", n)); } + // Self-healing: detect validators with penalty_percent > 0 but no + // corresponding expire records (orphaned penalties from incomplete + // snapshot migration). Reset them so counted_votes reflects true votes. + { + uint32_t healed = 0; + const auto& val_idx = db.get_index().indices(); + const auto& pe_idx = db.get_index().indices().get(); + for (auto itr = val_idx.begin(); itr != val_idx.end(); ++itr) { + if (itr->penalty_percent > 0) { + // Check if there are any matching expire records + auto pe_itr = pe_idx.find(itr->owner); + if (pe_itr == pe_idx.end()) { + // Orphaned penalty: no expire record exists + db.modify(*itr, [&](validator_object& w) { + wlog("Self-healing: validator '${v}' has penalty_percent=${p} but no expire records, resetting", + ("v", w.owner)("p", w.penalty_percent)); + w.penalty_percent = 0; + w.counted_votes = w.votes; + }); + ++healed; + } + } + } + if (healed > 0) { + ilog(CLOG_ORANGE "Self-healing: reset ${n} orphaned validator penalties" CLOG_RESET, ("n", healed)); + } + } + // Set the chainbase revision to match the snapshot head block db.set_revision(header.snapshot_block_num); @@ -1776,17 +1851,17 @@ void snapshot_plugin::plugin_impl::on_applied_block(const graphene::protocol::si return; } - // Helper lambda: check if local witness is scheduled to produce soon. + // Helper lambda: check if local validator is scheduled to produce soon. // When returning true, also stores the slot time of the earliest upcoming - // witness production in pending_snapshot_safe_after_time so the deferred + // validator production in pending_snapshot_safe_after_time so the deferred // snapshot can wait until after that slot is filled. - auto is_witness_producing_soon = [&]() -> bool { + auto is_validator_producing_soon = [&]() -> bool { try { - auto* witness_plug = appbase::app().find_plugin(); - if (witness_plug != nullptr && witness_plug->get_state() == appbase::abstract_plugin::started) { - bool soon = witness_plug->is_witness_scheduled_soon(); + auto* validator_plug = appbase::app().find_plugin(); + if (validator_plug != nullptr && validator_plug->get_state() == appbase::abstract_plugin::started) { + bool soon = validator_plug->is_validator_scheduled_soon(); if (soon) { - pending_snapshot_safe_after_time = witness_plug->get_next_validator_slot_time(); + pending_snapshot_safe_after_time = validator_plug->get_next_validator_slot_time(); } return soon; } @@ -1830,7 +1905,7 @@ void snapshot_plugin::plugin_impl::on_applied_block(const graphene::protocol::si // Guard clears snapshot_in_progress on scope exit. // release() disables the destructor once the DB read lock drops — // compression and file I/O below don't block the write lock, - // so the witness can produce as soon as the lock is released. + // so the validator can produce as soon as the lock is released. struct flag_guard { std::atomic& flag; bool released = false; @@ -1844,7 +1919,7 @@ void snapshot_plugin::plugin_impl::on_applied_block(const graphene::protocol::si bool p2p_resumed = false; try { create_snapshot(output, [&p2p_resumed, &guard, p2p_plug]() { - // DB read lock just dropped — resume P2P and unblock the witness. + // DB read lock just dropped — resume P2P and unblock the validator. // Compression and file I/O that follow don't hold any DB lock. if (p2p_plug && p2p_plug->get_state() == appbase::abstract_plugin::started) { p2p_plug->resume_block_processing(); @@ -1874,18 +1949,18 @@ void snapshot_plugin::plugin_impl::on_applied_block(const graphene::protocol::si }; // Handle deferred (pending) snapshot from a previous block. - // The witness check was already performed once when the snapshot was originally - // deferred. We do NOT re-check is_witness_producing_soon() here to avoid an - // infinite deferral loop where the witness is always scheduled soon. + // The validator check was already performed once when the snapshot was originally + // deferred. We do NOT re-check is_validator_producing_soon() here to avoid an + // infinite deferral loop where the validator is always scheduled soon. // - // Instead, we wait for the specific witness slot to be filled: the deferred + // Instead, we wait for the specific validator slot to be filled: the deferred // snapshot only fires once head_block_time() >= pending_snapshot_safe_after_time, - // meaning the witness's block has been produced and applied (or the slot was + // meaning the validator's block has been produced and applied (or the slot was // missed and the chain moved past it). This prevents the snapshot from starting - // while the witness is about to produce. + // while the validator is about to produce. if (snapshot_pending && !is_syncing) { // If safe_after_time is epoch (lookup failed), fire immediately as fallback. - // If head_block_time has reached/passed the witness slot time, the block + // If head_block_time has reached/passed the validator slot time, the block // at that slot has been applied (or the slot was skipped by a gap). bool safe_to_fire = (pending_snapshot_safe_after_time == fc::time_point_sec()) || (db.head_block_time() >= pending_snapshot_safe_after_time); @@ -1910,7 +1985,7 @@ void snapshot_plugin::plugin_impl::on_applied_block(const graphene::protocol::si } else { output = fc::path(snapshot_dir) / ("snapshot-block-" + std::to_string(block_num) + ".vizjson"); } - if (is_witness_producing_soon()) { + if (is_validator_producing_soon()) { ilog(CLOG_GREEN "Deferring snapshot-at-block ${b}: validator scheduled to produce next block" CLOG_RESET, ("b", block_num)); snapshot_pending = true; pending_snapshot_path = output.string(); @@ -1927,7 +2002,7 @@ void snapshot_plugin::plugin_impl::on_applied_block(const graphene::protocol::si needs_fresh_snapshot = false; std::string dir = snapshot_dir; fc::path output = fc::path(dir) / ("snapshot-block-" + std::to_string(block_num) + ".vizjson"); - if (is_witness_producing_soon()) { + if (is_validator_producing_soon()) { ilog(CLOG_GREEN "Deferring urgent fresh snapshot at block ${b}: validator scheduled" CLOG_RESET, ("b", block_num)); snapshot_pending = true; pending_snapshot_path = output.string(); @@ -1941,7 +2016,7 @@ void snapshot_plugin::plugin_impl::on_applied_block(const graphene::protocol::si if (snapshot_every_n_blocks > 0 && block_num % snapshot_every_n_blocks == 0 && !is_syncing) { std::string dir = snapshot_dir; fc::path output = fc::path(dir) / ("snapshot-block-" + std::to_string(block_num) + ".vizjson"); - if (is_witness_producing_soon()) { + if (is_validator_producing_soon()) { ilog(CLOG_GREEN "Deferring periodic snapshot at block ${b}: validator scheduled to produce next block" CLOG_RESET, ("b", block_num)); snapshot_pending = true; pending_snapshot_path = output.string(); @@ -2030,9 +2105,9 @@ void snapshot_plugin::plugin_impl::check_stalled_sync_loop() { // Skip stalled sync recovery entirely. bool we_are_master = false; try { - auto* witness_plug = appbase::app().find_plugin(); - if (witness_plug && witness_plug->get_state() == appbase::abstract_plugin::started) { - we_are_master = witness_plug->is_emergency_master(); + auto* validator_plug = appbase::app().find_plugin(); + if (validator_plug && validator_plug->get_state() == appbase::abstract_plugin::started) { + we_are_master = validator_plug->is_emergency_master(); } } catch (...) {} @@ -3742,7 +3817,7 @@ void snapshot_plugin::plugin_initialize(const bpo::variables_map& options) { // Register snapshot creation callback on the chain plugin. // This ensures the snapshot is created AFTER full DB load (including replay), - // but BEFORE on_sync() — so P2P/witness never start. + // but BEFORE on_sync() — so P2P/validator never start. if (!my->create_snapshot_path.empty()) { auto& chain_plug = appbase::app().get_plugin(); chain_plug.snapshot_create_callback = [this]() { @@ -3837,7 +3912,7 @@ void snapshot_plugin::plugin_startup() { // Note: --create-snapshot is handled via snapshot_create_callback registered // in plugin_initialize(). It runs during chain plugin's startup, after full DB load - // (including replay), but before on_sync() — so P2P/witness never start. + // (including replay), but before on_sync() — so P2P/validator never start. // Note: --sync-snapshot-from-trusted-peer is handled via snapshot_p2p_sync_callback // registered in plugin_initialize(). It runs during chain plugin's startup when diff --git a/plugins/validator/include/graphene/plugins/validator/validator.hpp b/plugins/validator/include/graphene/plugins/validator/validator.hpp index c1d06013fb..68c330e873 100644 --- a/plugins/validator/include/graphene/plugins/validator/validator.hpp +++ b/plugins/validator/include/graphene/plugins/validator/validator.hpp @@ -76,7 +76,7 @@ namespace graphene { bool is_witness_scheduled_soon() const { return is_validator_scheduled_soon(); } /// Returns true if this node is the emergency master: holds the - /// emergency-private-key (committee is in _witnesses) AND committee + /// emergency-private-key (committee is in _validators) AND committee /// appears in the current witness schedule. Only the master should /// produce blocks solo during emergency consensus; all other nodes /// are followers that must sync from the network. diff --git a/plugins/validator/validator.cpp b/plugins/validator/validator.cpp index d37dac3045..ea87e41ee5 100644 --- a/plugins/validator/validator.cpp +++ b/plugins/validator/validator.cpp @@ -128,7 +128,7 @@ namespace graphene { block_validation_condition::block_validation_condition_enum maybe_validate_block(fc::mutable_variant_object &capture); boost::program_options::variables_map _options; - uint32_t _required_witness_participation = 33 * CHAIN_1_PERCENT; + uint32_t _required_validator_participation = 33 * CHAIN_1_PERCENT; std::atomic head_block_num_; block_id_type head_block_id_ = block_id_type(); @@ -145,13 +145,13 @@ namespace graphene { asio::deadline_timer production_timer_; std::map _private_keys; - std::set _witnesses; + std::set _validators; fc::time_point last_block_post_validation_time; // Fork collision resolution state uint32_t fork_collision_defer_count_ = 0; - uint32_t _fork_collision_timeout_blocks = 21; // one full witness round (21 blocks = 63s) + uint32_t _fork_collision_timeout_blocks = 21; // one full validator round (21 blocks = 63s) // Minority fork recovery state: tracks when we rolled back to // LIB and are waiting for P2P sync to catch up before @@ -164,13 +164,13 @@ namespace graphene { uint32_t _slot_zero_streak = 0; fc::time_point _slot_zero_streak_start; - // Track consecutive not_my_turn results to detect when our witness - // is in the schedule but slots keep belonging to other witnesses. - // Helps diagnose "silent miss" issues where the witness should have + // Track consecutive not_my_turn results to detect when our validator + // is in the schedule but slots keep belonging to other validators. + // Helps diagnose "silent miss" issues where the validator should have // produced but didn't (schedule misalignment, timing issues, etc). uint32_t _not_my_turn_streak = 0; fc::time_point _not_my_turn_streak_start; - std::string _last_scheduled_witness; // last witness that got the slot + std::string _last_scheduled_validator; // last validator that got the slot // Production watchdog: tracks when we last produced a block // so the watchdog can fire if the emergency master goes silent. @@ -197,7 +197,7 @@ namespace graphene { bool _debug_block_production_config = false; // Slot hijack detection: counts consecutive blocks where committee - // filled a slot that was assigned to our witness in the shuffled + // filled a slot that was assigned to our validator in the shuffled // schedule. In DLT emergency mode the emergency master may blank // our signing key and produce committee blocks in our slots; this // counter makes the condition visible in watchdog diagnostics. @@ -214,7 +214,7 @@ namespace graphene { std::mutex _diag_mutex; // applied_block signal handler: detects when incoming blocks - // reveal missed slots, and if our witness was scheduled for + // reveal missed slots, and if our validator was scheduled for // any of them, dumps full plugin state for diagnosis. void on_block_applied(const graphene::chain::signed_block &block); }; @@ -222,13 +222,13 @@ namespace graphene { void validator_plugin::set_program_options( boost::program_options::options_description &command_line_options, boost::program_options::options_description &config_file_options) { - string witness_id_example = "initwitness"; + string validator_id_example = "initvalidator"; command_line_options.add_options() ("enable-stale-production", bpo::value()->implicit_value(true) , "Enable block production, even if the chain is stale.") ("required-participation", bpo::value()->default_value(33 * CHAIN_1_PERCENT), "Percent of validators (0-99) that must be participating in order to produce blocks") - ("validator,v", bpo::value>()->composing()->multitoken(), ("name of validator controlled by this node (e.g. " + witness_id_example + " )").c_str()) - ("witness,w", bpo::value>()->composing()->multitoken(), "[DEPRECATED] Use --validator. Name of validator controlled by this node.") + ("validator,v", bpo::value>()->composing()->multitoken(), ("name of validator controlled by this node (e.g. " + validator_id_example + " )").c_str()) + ("witness,w", bpo::value>()->composing()->multitoken(), "[DEPRECATED] Use --validator. Name of validator controlled by this node (legacy 'witness' option, kept for config.ini backward compatibility).") ("private-key", bpo::value>()->composing()->multitoken(), "WIF PRIVATE KEY to be used by one or more validators") ("emergency-private-key", bpo::value>()->composing()->multitoken(), "WIF PRIVATE KEY for emergency consensus block production. " @@ -272,13 +272,13 @@ namespace graphene { pimpl->total_hashes_.store(0, std::memory_order_relaxed); pimpl->_options = &options; - LOAD_VALUE_SET(options, "validator", pimpl->_witnesses, string) + LOAD_VALUE_SET(options, "validator", pimpl->_validators, string) if (options.count("witness")) { - // Deprecated: --witness is kept for config.ini backward compatibility. + // Deprecated: --witness / config 'witness' is kept for backward compatibility. wlog("Config option 'witness' is deprecated, use 'validator' instead."); - LOAD_VALUE_SET(options, "witness", pimpl->_witnesses, string) + LOAD_VALUE_SET(options, "witness", pimpl->_validators, string) } - edump((pimpl->_witnesses)); + edump((pimpl->_validators)); if(options.count("enable-stale-production")){ if (options["enable-stale-production"].as()) { @@ -287,7 +287,7 @@ namespace graphene { } if(options.count("required-participation")){ - pimpl->_required_witness_participation = options["required-participation"].as(); + pimpl->_required_validator_participation = options["required-participation"].as(); } if (options.count("private-key")) { @@ -306,9 +306,9 @@ namespace graphene { FC_ASSERT(private_key.valid(), "unable to parse emergency private key"); pimpl->_private_keys[private_key->get_public_key()] = *private_key; } - // Add the committee account to our witness set so we produce blocks + // Add the committee account to our validator set so we produce blocks // when the schedule assigns committee slots during emergency mode - pimpl->_witnesses.insert(CHAIN_EMERGENCY_VALIDATOR_ACCOUNT); + pimpl->_validators.insert(CHAIN_EMERGENCY_VALIDATOR_ACCOUNT); ilog("Emergency private key loaded. Will produce blocks during emergency consensus mode."); } @@ -356,17 +356,17 @@ namespace graphene { // Log validator configuration for post-crash diagnostics ilog("Validator config: ${n} validators, ${k} private keys", - ("n", pimpl->_witnesses.size())("k", pimpl->_private_keys.size())); - for (const auto& w : pimpl->_witnesses) { + ("n", pimpl->_validators.size())("k", pimpl->_private_keys.size())); + for (const auto& w : pimpl->_validators) { ilog(" configured validator: ${w}", ("w", w)); } - if (!pimpl->_witnesses.empty()) { - ilog("Launching block production for ${n} validators.", ("n", pimpl->_witnesses.size())); + if (!pimpl->_validators.empty()) { + ilog("Launching block production for ${n} validators.", ("n", pimpl->_validators.size())); pimpl->p2p().set_block_production(true); // Connect to applied_block signal to detect missed slots - // that belong to our witnesses and log diagnostic state. + // that belong to our validators and log diagnostic state. pimpl->_last_applied_block_num = d.head_block_num(); d.applied_block.connect([this](const graphene::chain::signed_block &block) { pimpl->on_block_applied(block); @@ -386,7 +386,7 @@ namespace graphene { void validator_plugin::plugin_shutdown() { graphene::time::shutdown_ntp_time(); - if (!pimpl->_witnesses.empty()) { + if (!pimpl->_validators.empty()) { ilog("shutting downing production timer"); // Stop the dedicated io_service so the production thread exits. // io_service::stop() is thread-safe; it causes run() to return @@ -409,7 +409,7 @@ namespace graphene { bool validator_plugin::is_validator_scheduled_soon() const { try { - if (!pimpl || pimpl->_witnesses.empty() || pimpl->_private_keys.empty()) { + if (!pimpl || pimpl->_validators.empty() || pimpl->_private_keys.empty()) { return false; } @@ -425,20 +425,20 @@ namespace graphene { // Check 5 upcoming slots (~15 seconds) to cover snapshot creation time (~10s) + safety margin for (uint32_t s = slot; s <= slot + 4; ++s) { - string scheduled_witness = db.get_scheduled_validator(s); - if (pimpl->_witnesses.find(scheduled_witness) == pimpl->_witnesses.end()) { + string scheduled_validator = db.get_scheduled_validator(s); + if (pimpl->_validators.find(scheduled_validator) == pimpl->_validators.end()) { continue; } - const auto& witness_by_name = db.get_index().indices().get(); - auto itr = witness_by_name.find(scheduled_witness); - if (itr == witness_by_name.end()) { + const auto& validator_by_name = db.get_index().indices().get(); + auto itr = validator_by_name.find(scheduled_validator); + if (itr == validator_by_name.end()) { continue; } graphene::protocol::public_key_type scheduled_key = itr->signing_key; if (scheduled_key == graphene::protocol::public_key_type()) { - continue; // Disabled witness (zero key) + continue; // Disabled validator (zero key) } if (pimpl->_private_keys.find(scheduled_key) != pimpl->_private_keys.end()) { @@ -456,7 +456,7 @@ namespace graphene { fc::time_point_sec validator_plugin::get_next_validator_slot_time() const { try { - if (!pimpl || pimpl->_witnesses.empty() || pimpl->_private_keys.empty()) { + if (!pimpl || pimpl->_validators.empty() || pimpl->_private_keys.empty()) { return fc::time_point_sec(); } @@ -471,20 +471,20 @@ namespace graphene { } for (uint32_t s = slot; s <= slot + 4; ++s) { - string scheduled_witness = db.get_scheduled_validator(s); - if (pimpl->_witnesses.find(scheduled_witness) == pimpl->_witnesses.end()) { + string scheduled_validator = db.get_scheduled_validator(s); + if (pimpl->_validators.find(scheduled_validator) == pimpl->_validators.end()) { continue; } - const auto& witness_by_name = db.get_index().indices().get(); - auto itr = witness_by_name.find(scheduled_witness); - if (itr == witness_by_name.end()) { + const auto& validator_by_name = db.get_index().indices().get(); + auto itr = validator_by_name.find(scheduled_validator); + if (itr == validator_by_name.end()) { continue; } graphene::protocol::public_key_type scheduled_key = itr->signing_key; if (scheduled_key == graphene::protocol::public_key_type()) { - continue; // Disabled witness (zero key) + continue; // Disabled validator (zero key) } if (pimpl->_private_keys.find(scheduled_key) != pimpl->_private_keys.end()) { @@ -503,18 +503,18 @@ namespace graphene { bool validator_plugin::is_emergency_master() const { try { - if (!pimpl || pimpl->_witnesses.empty()) { + if (!pimpl || pimpl->_validators.empty()) { return false; } // Condition 1: we hold the emergency-private-key. - // CHAIN_EMERGENCY_VALIDATOR_ACCOUNT is added to _witnesses only + // CHAIN_EMERGENCY_VALIDATOR_ACCOUNT is added to _validators only // when --emergency-private-key is configured (see plugin_initialize). - if (pimpl->_witnesses.find(CHAIN_EMERGENCY_VALIDATOR_ACCOUNT) == pimpl->_witnesses.end()) { + if (pimpl->_validators.find(CHAIN_EMERGENCY_VALIDATOR_ACCOUNT) == pimpl->_validators.end()) { return false; } - // Condition 2: the committee account is in the current witness schedule. + // Condition 2: the committee account is in the current validator schedule. auto& db = pimpl->database(); return db.with_weak_read_lock([&]() -> bool { const validator_schedule_object& wso = db.get_validator_schedule_object(); @@ -535,12 +535,12 @@ namespace graphene { bool validator_plugin::is_emergency_key_configured() const { try { - if (!pimpl || pimpl->_witnesses.empty()) { + if (!pimpl || pimpl->_validators.empty()) { return false; } - // CHAIN_EMERGENCY_VALIDATOR_ACCOUNT is added to _witnesses only + // CHAIN_EMERGENCY_VALIDATOR_ACCOUNT is added to _validators only // when --emergency-private-key is configured (see plugin_initialize). - return pimpl->_witnesses.find(CHAIN_EMERGENCY_VALIDATOR_ACCOUNT) != pimpl->_witnesses.end(); + return pimpl->_validators.find(CHAIN_EMERGENCY_VALIDATOR_ACCOUNT) != pimpl->_validators.end(); } catch (...) { return false; } @@ -579,14 +579,14 @@ namespace graphene { _last_applied_block_num = block_num; // === SLOT-HIJACK DETECTION (runs for every block) === - // In DLT emergency mode, the emergency master may blank our witness's + // In DLT emergency mode, the emergency master may blank our validator's // signing_key and fill our scheduled slots with committee blocks. This // detection runs for every incoming block and checks whether the slot - // that was just filled was assigned to our witness but produced by someone + // that was just filled was assigned to our validator but produced by someone // else (committee / emergency account). The counter is included in // watchdog diagnostics so the operator can see the hijack pattern. const auto& dgp_hijack = database().get_dynamic_global_properties(); - if (database()._dlt_mode && !_witnesses.empty() + if (database()._dlt_mode && !_validators.empty() && prev_num > 0 && block_num == prev_num + 1 && dgp_hijack.emergency_consensus_active) { const auto& wso_sj = database().get_validator_schedule_object(); @@ -595,14 +595,14 @@ namespace graphene { // apply_block increments current_aslot to the applied block's slot // before this callback fires, so current_aslot IS the applied slot. uint64_t slot_idx = dgp_hijack.current_aslot % nsw_sj; - const std::string& expected_witness = + const std::string& expected_validator = wso_sj.current_shuffled_validators[slot_idx]; - bool was_our_slot = _witnesses.count(expected_witness) > 0; - // True hijack only if the actual producer is NOT also one of our witnesses. - bool producer_is_ours = _witnesses.count(block.validator) > 0; + bool was_our_slot = _validators.count(expected_validator) > 0; + // True hijack only if the actual producer is NOT also one of our validators. + bool producer_is_ours = _validators.count(block.validator) > 0; - if (was_our_slot && !producer_is_ours && block.validator != expected_witness) { - // External witness (committee / emergency) produced at our slot. + if (was_our_slot && !producer_is_ours && block.validator != expected_validator) { + // External validator (committee / emergency) produced at our slot. _slot_hijack_count++; _slot_hijack_height = static_cast(block_num); // Log the first 3 hijacks, then once per minute. @@ -614,14 +614,14 @@ namespace graphene { elog("SLOT-HIJACK: block #${bn} by '${wit}' but slot was assigned " "to our validator '${exp}' (hijack #${cnt}). " "head=#${head} aslot=${aslot} num_sched=${nsched}", - ("bn", block_num)("wit", block.validator)("exp", expected_witness) + ("bn", block_num)("wit", block.validator)("exp", expected_validator) ("cnt", _slot_hijack_count) ("head", dgp_hijack.head_block_number) ("aslot", (uint64_t)dgp_hijack.current_aslot) ("nsched", nsw_sj)); } - } else if (was_our_slot && (block.validator == expected_witness || producer_is_ours)) { - // Our witness (expected or another of ours) produced — reset hijack counter. + } else if (was_our_slot && (block.validator == expected_validator || producer_is_ours)) { + // Our validator (expected or another of ours) produced — reset hijack counter. if (_slot_hijack_count > 0) { wlog("SLOT-HIJACK-RESOLVED: our validator '${wit}' produced " "block #${bn} after ${cnt} hijacked slot(s).", @@ -648,28 +648,28 @@ namespace graphene { const auto &dgp = database().get_dynamic_global_properties(); const auto &wso = database().get_validator_schedule_object(); uint64_t cur_aslot = dgp.current_aslot; - uint32_t num_witnesses = wso.num_scheduled_validators; - if (num_witnesses == 0) return; + uint32_t num_validators = wso.num_scheduled_validators; + if (num_validators == 0) return; - // Check each missed slot to see if our witness was scheduled - bool our_witness_missed = false; - std::string missed_witnesses_list; + // Check each missed slot to see if our validator was scheduled + bool our_validator_missed = false; + std::string missed_validators_list; for (uint32_t i = 0; i < missed_count && i < 100; ++i) { uint64_t abs_slot = cur_aslot - missed_count + i; - const std::string &wname = wso.current_shuffled_validators[abs_slot % num_witnesses]; - if (!missed_witnesses_list.empty()) missed_witnesses_list += ","; - missed_witnesses_list += wname; - if (_witnesses.count(wname) > 0) { - our_witness_missed = true; + const std::string &wname = wso.current_shuffled_validators[abs_slot % num_validators]; + if (!missed_validators_list.empty()) missed_validators_list += ","; + missed_validators_list += wname; + if (_validators.count(wname) > 0) { + our_validator_missed = true; } } - if (!our_witness_missed) { - // Not our problem — other witnesses missed their slots + if (!our_validator_missed) { + // Not our problem — other validators missed their slots return; } - // Our witness missed a slot! Dump full diagnostic state. + // Our validator missed a slot! Dump full diagnostic state. fc::time_point_sec now_ts = graphene::time::now(); int64_t ntp_us = 0; try { ntp_us = graphene::time::ntp_error().count(); } catch (...) {} @@ -679,20 +679,20 @@ namespace graphene { bool dlt_syncing = false; try { dlt_syncing = chain().is_syncing(); } catch (...) {} - std::string witness_names; - for (const auto &w : _witnesses) { - if (!witness_names.empty()) witness_names += ","; - witness_names += w; + std::string validator_names; + for (const auto &w : _validators) { + if (!validator_names.empty()) validator_names += ","; + validator_names += w; } fc::time_point_sec next_slot = database().get_slot_time(1); std::string next_scheduled = database().get_scheduled_validator(1); - // Check on-chain signing key status for our witnesses + // Check on-chain signing key status for our validators std::string key_status; const auto &wit_idx = database().get_index() .indices().get(); - for (const auto &wname : _witnesses) { + for (const auto &wname : _validators) { auto witr = wit_idx.find(wname); if (!key_status.empty()) key_status += " "; if (witr != wit_idx.end()) { @@ -712,17 +712,17 @@ namespace graphene { "ntp_offset=${ntp}us now=${now} next_slot_time=${nst} next_scheduled=${nsw} " "validators=[${wn}] keys=[${ks}]", ("bn", block_num)("missed", missed_count)("prev", prev_num) - ("mw", missed_witnesses_list) + ("mw", missed_validators_list) ("ep", _ever_produced) ("mr", _minority_fork_recovering) ("sr", _last_slot_result)("nmts", _not_my_turn_streak) ("sz", _slot_zero_streak) ("ds", dlt_syncing)("cu", catching_up) ("h", dgp.head_block_number)("a", cur_aslot) - ("ns", num_witnesses) + ("ns", num_validators) ("ntp", ntp_us)("now", now_ts) ("nst", next_slot)("nsw", next_scheduled) - ("wn", witness_names)("ks", key_status)); + ("wn", validator_names)("ks", key_status)); } catch (...) { // Non-critical diagnostic — never disrupt block processing } @@ -858,17 +858,17 @@ namespace graphene { _nmt_snap = _not_my_turn_streak; } if (_nmt_snap == 500) { - // ~125s with slot>0 but not our witness — investigate. + // ~125s with slot>0 but not our validator — investigate. // _not_my_turn_streak_start is production-only; no lock needed. auto elapsed = fc::time_point::now() - _not_my_turn_streak_start; wlog("NOT_MY_TURN STREAK: ${n} consecutive slots (${s}s) went to other validators. " "Last scheduled: ${sw}. Our validators: ${ow}. " "Check: is our validator still in shuffled schedule?", ("n", _nmt_snap)("s", elapsed.count() / 1000000) - ("sw", _last_scheduled_witness) - ("ow", [_witnesses = _witnesses]() { + ("sw", _last_scheduled_validator) + ("ow", [_validators = _validators]() { std::string s; - for (const auto& w : _witnesses) { if (!s.empty()) s += ","; s += w; } + for (const auto& w : _validators) { if (!s.empty()) s += ","; s += w; } return s; }())); } @@ -910,7 +910,7 @@ namespace graphene { try { _drift_us = graphene::time::ntp_error().count(); } catch (...) {} int64_t _gap_ms = (_nst_init - _now_init).count() / 1000; std::string _next_w3 = database().get_scheduled_validator(1); - bool _ours3 = _witnesses.count(_next_w3) > 0; + bool _ours3 = _validators.count(_next_w3) > 0; wlog("SLOT=0 STREAK: ${n} consecutive not_time_yet. " "now=${now} head_block_time=${hbt} (drift=${d}us) " "next_slot=${nst} (gap=${g}ms) next_validator=${nw} is_ours=${o} head=#${h}.", @@ -928,7 +928,7 @@ namespace graphene { try { _drift10 = graphene::time::ntp_error().count(); } catch (...) {} int64_t _gap_ms = (_nst10 - _now10).count() / 1000; std::string _next_w10 = database().get_scheduled_validator(1); - bool _ours10 = _witnesses.count(_next_w10) > 0; + bool _ours10 = _validators.count(_next_w10) > 0; wlog("slot=0 streak: ${n} consecutive not_time_yet (${s}s elapsed). " "now=${now}, head_block_time=${hbt}, next_slot_time=${nst}. " "Time to next slot: ${g}ms. NTP drift: ${d}us. " @@ -952,7 +952,7 @@ namespace graphene { bool dlt_syncing = false; try { dlt_syncing = chain().is_syncing(); } catch (...) {} std::string _next_w60 = database().get_scheduled_validator(1); - bool _ours60 = _witnesses.count(_next_w60) > 0; + bool _ours60 = _validators.count(_next_w60) > 0; elog("SLOT=0 PROLONGED STALL: ${n} consecutive not_time_yet (${s}s). " "head_block_time=${hbt} is ${f}ms AHEAD of now=${now}! " "next_slot_time=${nst} next_validator=${nw} is_ours=${o}, NTP drift=${d}us. " @@ -983,7 +983,7 @@ namespace graphene { shuffled_top3 += wso120.current_shuffled_validators[i]; } std::string _next_w120 = database().get_scheduled_validator(1); - bool _ours120 = _witnesses.count(_next_w120) > 0; + bool _ours120 = _validators.count(_next_w120) > 0; elog("CRITICAL: slot=0 stall for ${s}s! head_block_time=${hbt} is ${f}ms in the future " "relative to NTP time (now=${now}). next_slot_time=${nst} next_validator=${nw} is_ours=${o}, NTP drift=${d}us. " "Network is stalled. catching_up=${c}, dlt_syncing=${ds}, head=#${h}. " @@ -1032,7 +1032,7 @@ namespace graphene { // Production watchdog: elog if we've produced before but have gone // silent for too long while production is still enabled. // Emergency master threshold: 60s (before 315s blanking at 105 missed blocks). - // Regular witness threshold: 180s (before 600s blanking at 200 missed blocks). + // Regular validator threshold: 180s (before 600s blanking at 200 missed blocks). // Fires every 30s once triggered so the operator has multiple chances to react. // // When returning from a lag condition, skip ahead past the missed slot @@ -1065,15 +1065,15 @@ namespace graphene { const auto& dgp_watch = database().get_dynamic_global_properties(); // Production should be active if: // - Not in minority fork recovery - // - Witnesses are configured + // - Validators are configured // - Either emergency master OR network is healthy (participation >= 33%) - if (!_minority_fork_recovering && !_witnesses.empty()) { + if (!_minority_fork_recovering && !_validators.empty()) { if (dgp_watch.emergency_consensus_active) { // Emergency mode: should produce if we have emergency key - should_be_producing = (_witnesses.count(CHAIN_EMERGENCY_VALIDATOR_ACCOUNT) > 0); + should_be_producing = (_validators.count(CHAIN_EMERGENCY_VALIDATOR_ACCOUNT) > 0); } else { // Normal mode: should produce if participation is healthy - uint32_t prate_watch = database().witness_participation_rate(); + uint32_t prate_watch = database().validator_participation_rate(); should_be_producing = (prate_watch >= 33 * CHAIN_1_PERCENT); } } @@ -1081,7 +1081,7 @@ namespace graphene { if (should_be_producing) { auto silent_for = fc::time_point::now() - _last_production_time; - bool is_emrg_master = _witnesses.count(CHAIN_EMERGENCY_VALIDATOR_ACCOUNT) > 0; + bool is_emrg_master = _validators.count(CHAIN_EMERGENCY_VALIDATOR_ACCOUNT) > 0; int64_t threshold_us = is_emrg_master ? 60000000 : 180000000; if (silent_for.count() > threshold_us) { // === AUTO-ENABLE DEBUG LOGGING ON FIRST WATCHDOG FIRE === @@ -1104,39 +1104,39 @@ namespace graphene { try { catching_up = p2p().is_catching_up_after_pause(); } catch (...) {} bool dlt_syncing = false; try { dlt_syncing = chain().is_syncing(); } catch (...) {} - std::string witness_names; - for (const auto& w : _witnesses) { if (!witness_names.empty()) witness_names += ","; witness_names += w; } + std::string validator_names; + for (const auto& w : _validators) { if (!validator_names.empty()) validator_names += ","; validator_names += w; } int64_t ntp_us = 0; try { ntp_us = graphene::time::ntp_error().count(); } catch (...) {} // Who does the chain expect to produce right now? std::string scheduled_now = "?"; bool we_are_scheduled = false; - // How many of our witnesses appear anywhere in the full shuffled schedule? + // How many of our validators appear anywhere in the full shuffled schedule? uint32_t our_slots_in_schedule = 0; - // Which of our witnesses have zero on-chain signing key (blanked by emergency consensus)? + // Which of our validators have zero on-chain signing key (blanked by emergency consensus)? std::string blanked_keys; try { fc::time_point_sec now_sec = graphene::time::now() + fc::microseconds(250000); uint32_t cur_slot = db_wd.get_slot_at_time(now_sec); if (cur_slot > 0) { scheduled_now = db_wd.get_scheduled_validator(cur_slot); - we_are_scheduled = _witnesses.count(scheduled_now) > 0; + we_are_scheduled = _validators.count(scheduled_now) > 0; } else { // Between slots: show who gets the NEXT slot scheduled_now = "between_slots/" + db_wd.get_scheduled_validator(1); } - // Scan full shuffled schedule for our witnesses + // Scan full shuffled schedule for our validators const auto &wso_wd = db_wd.get_validator_schedule_object(); for (int i = 0; i < wso_wd.num_scheduled_validators; i++) { - if (_witnesses.count(wso_wd.current_shuffled_validators[i]) > 0) + if (_validators.count(wso_wd.current_shuffled_validators[i]) > 0) our_slots_in_schedule++; } - // Check on-chain signing keys for our witnesses + // Check on-chain signing keys for our validators const auto &wit_idx = db_wd.get_index().indices().get(); - for (const auto& w_name : _witnesses) { + for (const auto& w_name : _validators) { auto w_itr = wit_idx.find(w_name); if (w_itr != wit_idx.end() && w_itr->signing_key == graphene::protocol::public_key_type()) { @@ -1162,7 +1162,7 @@ namespace graphene { "ntp_offset=${n}us slot_hijacks=${shj} debug_logging=${dl}", ("t", is_emrg_master ? "emergency master" : "validator") ("s", silent_for.count() / 1000000) - ("w", witness_names) + ("w", validator_names) ("k", _private_keys.size()) ("sf", _production_skip_flags) ("mr", _minority_fork_recovering) @@ -1174,11 +1174,11 @@ namespace graphene { ("sw", scheduled_now) ("ws", we_are_scheduled) ("is", our_slots_in_schedule) - ("total", _witnesses.size()) + ("total", _validators.size()) ("bk", blanked_keys) ("sz", _slot_zero_streak) ("nmt", _not_my_turn_streak) - ("nmtw", _last_scheduled_witness) + ("nmtw", _last_scheduled_validator) ("n", ntp_us) ("shj", _shj_snap) ("dl", _watchdog_debug_enabled)); @@ -1196,11 +1196,11 @@ namespace graphene { // - Head is recent (external blocks arriving) // - Not in active P2P sync // - At least some peers connected - // - We have witnesses with valid keys in schedule + // - We have validators with valid keys in schedule bool head_advancing = (head_age_s >= 0 && head_age_s < 30); bool has_peers = false; try { has_peers = p2p().get_connections_count() > 0; } catch (...) {} - bool has_active_keys = (our_slots_in_schedule > 0 && blanked_keys.size() < witness_names.size()); + bool has_active_keys = (our_slots_in_schedule > 0 && blanked_keys.size() < validator_names.size()); if (head_advancing && !dlt_syncing && !catching_up && has_peers && has_active_keys) { bool did_recover = false; @@ -1278,7 +1278,7 @@ namespace graphene { if (db._debug_block_production) ilog("DEBUG_CRASH: dgp ok, head=${h} emergency=${e}", ("h", dgp.head_block_number)("e", dgp.emergency_consensus_active)); // === DLT MODE: DEFER PRODUCTION DURING ACTIVE SYNC === - // In DLT mode, the witness must not produce blocks while the + // In DLT mode, the validator must not produce blocks while the // chain is actively receiving sync blocks from P2P. Producing // during sync creates blocks on a stale head that conflict // with incoming blocks, causing "failed to link" errors and @@ -1297,12 +1297,12 @@ namespace graphene { // collisions and minority forks (p32.log). // // Outside DLT mode this check is NOT applied because normal - // witnesses must produce on the canonical chain head even + // validators must produce on the canonical chain head even // while the network is catching up. if (db._dlt_mode && chain().is_syncing()) { bool we_are_emergency_master = dgp.emergency_consensus_active && - _witnesses.find(CHAIN_EMERGENCY_VALIDATOR_ACCOUNT) != _witnesses.end(); + _validators.find(CHAIN_EMERGENCY_VALIDATOR_ACCOUNT) != _validators.end(); if (!we_are_emergency_master) { return block_validation_condition::not_synced; } @@ -1316,7 +1316,7 @@ namespace graphene { // during pause deadlocks on the write lock; producing after // pause but before drain creates a fork on a stale head. // - // This gate applies to ALL witness types (emergency and normal). + // This gate applies to ALL validator types (emergency and normal). // The flag is cleared when: pause ends + drain completes + // no peer is ahead (see drain_paused_block_queue / periodic_task). // @@ -1356,13 +1356,13 @@ namespace graphene { // producing on a stale head creates double-production // collisions and minority forks (p32.log). bool we_are_emergency_master = - _witnesses.find(CHAIN_EMERGENCY_VALIDATOR_ACCOUNT) != _witnesses.end(); - if (!we_are_emergency_master && _witnesses.empty()) { + _validators.find(CHAIN_EMERGENCY_VALIDATOR_ACCOUNT) != _validators.end(); + if (!we_are_emergency_master && _validators.empty()) { elog("EMERGENCY MODE ACTIVE but no validators configured! " "Block production impossible. Add --emergency-private-key to config."); } } else { - uint32_t prate = db.witness_participation_rate(); + uint32_t prate = db.validator_participation_rate(); if (prate >= 33 * CHAIN_1_PERCENT) { // HEALTHY NETWORK: enforce safe defaults automatically. // Even if operator has enable-stale-production=true in config, @@ -1375,7 +1375,7 @@ namespace graphene { // DISTRESSED NETWORK (participation < 33%, not yet emergency): // Honor manual config overrides -- operator may be trying to // accelerate recovery before the 1-hour timeout. - if (prate < _required_witness_participation) { + if (prate < _required_validator_participation) { if (_production_skip_flags & graphene::chain::database::skip_undo_history_check) { // enable-stale-production=true: operator override, produce anyway // to bootstrap/recover a fully stalled network where all nodes @@ -1388,12 +1388,12 @@ namespace graphene { // this node is likely in a minority network segment. // Producing here risks two partitions simultaneously // building chains — each seeing only the other segment's - // witnesses as absent, neither triggering minority_fork + // validators as absent, neither triggering minority_fork // detection below (which requires ALL recent fork_db // blocks to be ours). Stopping production is the safe // choice; use enable-stale-production=true to override // when you know the low participation is caused by - // offline witnesses rather than a partition. + // offline validators rather than a partition. capture("pct", uint32_t(prate / CHAIN_1_PERCENT)); return block_validation_condition::low_participation; } @@ -1404,74 +1404,74 @@ namespace graphene { // Pre-hardfork 12: no participation check here (done later) } - //try get block post validation list for each witness - //if witness can validate it, sign chain_id and block_id for message + //try get block post validation list for each validator + //if validator can validate it, sign chain_id and block_id for message //broadcast validation message by p2p plugin if (db._debug_block_production) ilog("DEBUG_CRASH: emergency/participation check done, entering block_post_validation"); if(last_block_post_validation_time < now_fine ){ last_block_post_validation_time = now; - if (db._debug_block_production) ilog("DEBUG_CRASH: block_post_validation tick, iterating ${n} validators", ("n", _witnesses.size())); + if (db._debug_block_production) ilog("DEBUG_CRASH: block_post_validation tick, iterating ${n} validators", ("n", _validators.size())); - // Pre-compute the current scheduled witnesses set so we can skip - // configured witnesses that are not actually scheduled. A witness + // Pre-compute the current scheduled validators set so we can skip + // configured validators that are not actually scheduled. A validator // that is not in the current schedule cannot contribute to LIB // advancement and broadcasting their post-validation is wasted // bandwidth and CPU. const validator_schedule_object &wso = db.get_validator_schedule_object(); - std::set scheduled_witnesses_set; + std::set scheduled_validators_set; for (int i = 0; i < wso.num_scheduled_validators; i += CHAIN_BLOCK_VALIDATOR_REPEAT) { if (wso.current_shuffled_validators[i] != account_name_type()) { - scheduled_witnesses_set.insert(wso.current_shuffled_validators[i]); + scheduled_validators_set.insert(wso.current_shuffled_validators[i]); } } - //get block post validation for each witness we have - for (auto &witness_account : _witnesses) { - // Skip witnesses not in the current schedule — they cannot + //get block post validation for each validator we have + for (auto &validator_account : _validators) { + // Skip validators not in the current schedule — they cannot // contribute to block post validation and broadcasting their // signatures is pointless network spam. - if (scheduled_witnesses_set.find(witness_account) == scheduled_witnesses_set.end()) { + if (scheduled_validators_set.find(validator_account) == scheduled_validators_set.end()) { continue; } - bool ignore_witness = false; - if (db._debug_block_production) ilog("DEBUG_CRASH: get_validator_confirmations for ${w}", ("w", witness_account)); - auto block_post_validations = db.get_validator_confirmations(witness_account); - if (db._debug_block_production) ilog("DEBUG_CRASH: got ${n} post_validations for ${w}", ("n", block_post_validations.size())("w", witness_account)); + bool ignore_validator = false; + if (db._debug_block_production) ilog("DEBUG_CRASH: get_validator_confirmations for ${w}", ("w", validator_account)); + auto block_post_validations = db.get_validator_confirmations(validator_account); + if (db._debug_block_production) ilog("DEBUG_CRASH: got ${n} post_validations for ${w}", ("n", block_post_validations.size())("w", validator_account)); if (block_post_validations.size() > 0) { - const auto &witness_by_name = db.get_index().indices().get(); - auto w_itr = witness_by_name.find(witness_account); - if (w_itr == witness_by_name.end()) { - wlog("Validator ${w} not found in validator index, skipping block post validation", ("w", witness_account)); + const auto &validator_by_name = db.get_index().indices().get(); + auto w_itr = validator_by_name.find(validator_account); + if (w_itr == validator_by_name.end()) { + wlog("Validator ${w} not found in validator index, skipping block post validation", ("w", validator_account)); continue; } - graphene::protocol::public_key_type witness_pub_key = w_itr->signing_key; + graphene::protocol::public_key_type validator_pub_key = w_itr->signing_key; - // Skip witnesses with zero/null signing key (intentionally disabled) - if (witness_pub_key == graphene::protocol::public_key_type()) { - ignore_witness = true; + // Skip validators with zero/null signing key (intentionally disabled) + if (validator_pub_key == graphene::protocol::public_key_type()) { + ignore_validator = true; } - auto private_key_itr = _private_keys.find(witness_pub_key); + auto private_key_itr = _private_keys.find(validator_pub_key); - if (!ignore_witness && private_key_itr == _private_keys.end()) { - ilog("No private key to public ${p} for ${w}", ("p", witness_pub_key)("w", witness_account)); - ignore_witness = true; + if (!ignore_validator && private_key_itr == _private_keys.end()) { + ilog("No private key to public ${p} for ${w}", ("p", validator_pub_key)("w", validator_account)); + ignore_validator = true; } - if(!ignore_witness){ - if (db._debug_block_production) ilog("DEBUG_CRASH: signing post_validations for ${w}", ("w", witness_account)); - graphene::protocol::private_key_type witness_priv_key = private_key_itr->second; - //we have block post validations for this witness + if(!ignore_validator){ + if (db._debug_block_production) ilog("DEBUG_CRASH: signing post_validations for ${w}", ("w", validator_account)); + graphene::protocol::private_key_type validator_priv_key = private_key_itr->second; + //we have block post validations for this validator //check if we have a block for(uint8_t i = 0; i < block_post_validations.size(); i++) { if(0 != block_post_validations[i].block_num){ if(block_post_validations[i].block_id != block_id_type()){ graphene::protocol::digest_type::encoder enc; fc::raw::pack(enc, db.get_chain_id().str().append(block_post_validations[i].block_id.str())); - //sign the enc by witness_priv_key - graphene::protocol::signature_type bpv_signature = witness_priv_key.sign_compact(enc.result()); - //ilog("Witness ${w} signed block post validation #${n} ${b} with signature ${s}", ("w", witness_account)("n", block_post_validations[i].block_num)("b", block_post_validations[i].block_id)("s", bpv_signature)); - p2p().post_broadcast_block_post_validation(block_post_validations[i].block_id, witness_account, bpv_signature); + //sign the enc by validator_priv_key + graphene::protocol::signature_type bpv_signature = validator_priv_key.sign_compact(enc.result()); + //ilog("Witness ${w} signed block post validation #${n} ${b} with signature ${s}", ("w", validator_account)("n", block_post_validations[i].block_num)("b", block_post_validations[i].block_id)("s", bpv_signature)); + p2p().post_broadcast_block_post_validation(block_post_validations[i].block_id, validator_account, bpv_signature); } } } @@ -1483,11 +1483,11 @@ namespace graphene { if (db._debug_block_production) ilog("DEBUG_CRASH: block_post_validation done, entering minority fork detection"); // === MINORITY FORK DETECTION === // If the last CHAIN_MAX_VALIDATORS (21) blocks in fork_db were ALL - // produced by our own configured witnesses, we are likely stuck on - // a minority fork where no external witnesses are participating. + // produced by our own configured validators, we are likely stuck on + // a minority fork where no external validators are participating. // // SKIP during emergency consensus: in emergency mode all blocks are - // produced by the committee account (which is in _witnesses), so the + // produced by the committee account (which is in _validators), so the // check would always falsely trigger and kill recovery. // // EXCEPTION: In DLT mode, even during emergency consensus, we apply @@ -1506,7 +1506,7 @@ namespace graphene { auto current = fork_head; while (current && blocks_checked < CHAIN_MAX_VALIDATORS) { - if (_witnesses.find(current->data.validator) == _witnesses.end()) { + if (_validators.find(current->data.validator) == _validators.end()) { all_ours = false; break; } @@ -1537,26 +1537,26 @@ namespace graphene { // === DLT-SPECIFIC MINORITY FORK DETECTION IN EMERGENCY MODE === // In emergency + DLT mode, the standard minority fork check above is // skipped because committee blocks are produced by an account that - // may be in _witnesses. However, a DLT emergency witness that has + // may be in _validators. However, a DLT emergency validator that has // lost its P2P connection to the master will produce blocks for its - // own witness slots AND the committee slots (because the emergency + // own validator slots AND the committee slots (because the emergency // key covers committee). After a few rounds with NO external blocks // at all, the node is on a minority fork. // // Detect this by checking whether the last full round (21 blocks) - // in fork_db contain ONLY blocks from our witnesses. In a healthy + // in fork_db contain ONLY blocks from our validators. In a healthy // emergency hybrid schedule, committee slots are filled by the master - // node's blocks — so we should see non-our-witness blocks regularly. + // node's blocks — so we should see non-our-validator blocks regularly. // If we don't, we're isolated. // // We use 1 round (21 blocks) because in a healthy emergency hybrid // schedule the committee (master) produces at least 1 block per // round, so we should never see 21 consecutive blocks from only - // our witnesses unless we're isolated from the master. This matches + // our validators unless we're isolated from the master. This matches // the standard non-emergency minority fork threshold. // // IMPORTANT: If committee (CHAIN_EMERGENCY_VALIDATOR_ACCOUNT) is in the - // current witness schedule AND we have its key (emergency-private-key + // current validator schedule AND we have its key (emergency-private-key // configured), this node IS the emergency master. All blocks being // "ours" is expected — other nodes sync from us. Skip minority fork // detection entirely to avoid false positives and the production @@ -1567,10 +1567,10 @@ namespace graphene { // nodes sync from us. Skip minority fork detection to prevent // false positives and the production deadlock. // Check both conditions: (a) committee is in the schedule, AND - // (b) we have its key (committee is in _witnesses only when + // (b) we have its key (committee is in _validators only when // emergency-private-key was configured — see plugin_initialize). bool we_are_master = false; - if (_witnesses.find(CHAIN_EMERGENCY_VALIDATOR_ACCOUNT) != _witnesses.end()) { + if (_validators.find(CHAIN_EMERGENCY_VALIDATOR_ACCOUNT) != _validators.end()) { const validator_schedule_object &wso = db.get_validator_schedule_object(); for (int i = 0; i < wso.num_scheduled_validators; i += CHAIN_BLOCK_VALIDATOR_REPEAT) { if (wso.current_shuffled_validators[i] == CHAIN_EMERGENCY_VALIDATOR_ACCOUNT) { @@ -1591,7 +1591,7 @@ namespace graphene { auto current = fork_head; while (current && blocks_checked < dlt_minority_threshold) { - if (_witnesses.find(current->data.validator) == _witnesses.end()) { + if (_validators.find(current->data.validator) == _validators.end()) { all_ours = false; break; } @@ -1619,7 +1619,7 @@ namespace graphene { // Guard lockless reads into shared memory with the resize barrier. // This prevents a concurrent shared memory resize from invalidating - // pointers while we read witness schedule, slot time, etc. + // pointers while we read validator schedule, slot time, etc. // The guard is released before generate_block() which has its own. if (db._debug_block_production) ilog("DEBUG_CRASH: creating op_guard"); fc::time_point _guard_enter = fc::time_point::now(); @@ -1634,14 +1634,14 @@ namespace graphene { now = now_fine + fc::microseconds(250000); // Detect op_guard stall crossing a slot boundary. - // A stall of 3+ seconds shifts 'now' into the next witness's slot, + // A stall of 3+ seconds shifts 'now' into the next validator's slot, // causing not_my_turn even when our slot just passed — silent miss. { int64_t _guard_ms = (fc::time_point::now() - _guard_enter).count() / 1000; if (_guard_ms > 100) { uint32_t _slot_before = db.get_slot_at_time(now_fine + fc::microseconds(250000) - fc::microseconds(_guard_ms * 1000)); std::string _wit_before = _slot_before > 0 ? db.get_scheduled_validator(_slot_before) : "none"; - bool _our_slot_lost = _slot_before > 0 && _witnesses.count(_wit_before) > 0; + bool _our_slot_lost = _slot_before > 0 && _validators.count(_wit_before) > 0; if (_our_slot_lost) { elog("VALIDATOR-SLOT-LOST: op_guard stall ${d}ms crossed slot boundary! " "missed slot for ${w} — now points to next slot after refresh. head=#${h}", @@ -1662,7 +1662,7 @@ namespace graphene { // Emergency master diagnostic: log when we are stuck at slot=0 and // real time is well past the expected next slot (i.e. we should have // a slot available but get_slot_at_time says 0 — NTP or head-time anomaly) - if (_witnesses.find(CHAIN_EMERGENCY_VALIDATOR_ACCOUNT) != _witnesses.end()) { + if (_validators.find(CHAIN_EMERGENCY_VALIDATOR_ACCOUNT) != _validators.end()) { const auto &_dgp2 = db.get_dynamic_global_properties(); if (_dgp2.emergency_consensus_active) { static fc::time_point _last_slot0_log; @@ -1712,15 +1712,15 @@ namespace graphene { assert(now > db.head_block_time()); if (db._debug_block_production) ilog("DEBUG_CRASH: get_scheduled_validator(${s})", ("s", slot)); - string scheduled_witness = db.get_scheduled_validator(slot); - if (db._debug_block_production) ilog("DEBUG_CRASH: scheduled_validator=${w}", ("w", scheduled_witness)); - // we must control the witness scheduled to produce the next block. - if (_witnesses.find(scheduled_witness) == _witnesses.end()) { - capture("scheduled_validator", scheduled_witness); - _last_scheduled_witness = scheduled_witness; // track for diagnostic + string scheduled_validator = db.get_scheduled_validator(slot); + if (db._debug_block_production) ilog("DEBUG_CRASH: scheduled_validator=${w}", ("w", scheduled_validator)); + // we must control the validator scheduled to produce the next block. + if (_validators.find(scheduled_validator) == _validators.end()) { + capture("scheduled_validator", scheduled_validator); + _last_scheduled_validator = scheduled_validator; // track for diagnostic // Emergency master diagnostic: log when committee is configured but // get_scheduled_validator returned a different name — reveals schedule misalignment - if (_witnesses.find(CHAIN_EMERGENCY_VALIDATOR_ACCOUNT) != _witnesses.end()) { + if (_validators.find(CHAIN_EMERGENCY_VALIDATOR_ACCOUNT) != _validators.end()) { const auto &_dgp3 = db.get_dynamic_global_properties(); if (_dgp3.emergency_consensus_active) { static fc::time_point _last_nmt_log; @@ -1730,7 +1730,7 @@ namespace graphene { const auto &_wso3 = db.get_validator_schedule_object(); dlog("EMRG-DIAG not_my_turn: slot=${s} scheduled=${sw} head=#${h} aslot=${a} num_sched=${ns} aslot_mod=${am}", ("s", slot) - ("sw", scheduled_witness) + ("sw", scheduled_validator) ("h", _dgp3.head_block_number) ("a", _dgp3.current_aslot) ("ns", _wso3.num_scheduled_validators) @@ -1742,9 +1742,9 @@ namespace graphene { } if (db._debug_block_production) ilog("DEBUG_CRASH: looking up validator in index"); - const auto &witness_by_name = db.get_index().indices().get(); - auto itr = witness_by_name.find(scheduled_witness); - if (db._debug_block_production) ilog("DEBUG_CRASH: validator found=${f}", ("f", itr != witness_by_name.end())); + const auto &validator_by_name = db.get_index().indices().get(); + auto itr = validator_by_name.find(scheduled_validator); + if (db._debug_block_production) ilog("DEBUG_CRASH: validator found=${f}", ("f", itr != validator_by_name.end())); fc::time_point_sec scheduled_time = db.get_slot_time(slot); graphene::protocol::public_key_type scheduled_key = itr->signing_key; @@ -1753,13 +1753,13 @@ namespace graphene { // Skip production if the scheduled slot time is at or before // the current head block time. This means the slot was already filled // by another block (e.g. received from P2P during/after a snapshot pause). - // Without this guard, the witness produces a competing block at the same + // Without this guard, the validator produces a competing block at the same // height, creating a micro-fork that propagates to all peers. // // This can happen when: // 1. Snapshot pauses P2P processing for several seconds - // 2. A block from another witness fills the slot during/after pause - // 3. Our witness production loop fires for a slot that's now occupied + // 2. A block from another validator fills the slot during/after pause + // 3. Our validator production loop fires for a slot that's now occupied if (scheduled_time <= db.head_block_time()) { wlog("Skipping block production: scheduled slot ${st} is at or before " "head_block_time ${hbt} (head=#${hn}). Slot was already filled.", @@ -1768,10 +1768,10 @@ namespace graphene { return block_validation_condition::not_time_yet; } - // Check if witness has zero/null signing key (intentionally disabled for block production) + // Check if validator has zero/null signing key (intentionally disabled for block production) if (scheduled_key == graphene::protocol::public_key_type()) { - if (scheduled_witness == CHAIN_EMERGENCY_VALIDATOR_ACCOUNT && - _witnesses.find(CHAIN_EMERGENCY_VALIDATOR_ACCOUNT) != _witnesses.end()) { + if (scheduled_validator == CHAIN_EMERGENCY_VALIDATOR_ACCOUNT && + _validators.find(CHAIN_EMERGENCY_VALIDATOR_ACCOUNT) != _validators.end()) { static fc::time_point _last_zerokey_log; auto _now_zk = fc::time_point::now(); if ((_now_zk - _last_zerokey_log).count() > 3000000) { @@ -1781,11 +1781,11 @@ namespace graphene { ("s", slot)("h", db.head_block_num()) ("a", db.get_dynamic_global_properties().current_aslot)); } - } else if (_witnesses.count(scheduled_witness)) { - // Our configured witness is scheduled but its on-chain signing_key is zero. + } else if (_validators.count(scheduled_validator)) { + // Our configured validator is scheduled but its on-chain signing_key is zero. // This means the chain blanked the key due to too many missed blocks // (database.cpp update_global_dynamic_data). Production is permanently - // blocked until the operator sends an update_witness transaction. + // blocked until the operator sends an update_validator transaction. static fc::time_point _last_zerokey_regular_log; auto _now_zkr = fc::time_point::now(); if ((_now_zkr - _last_zerokey_regular_log).count() > 60000000) { @@ -1793,7 +1793,7 @@ namespace graphene { elog("Validator ${w} scheduled at slot=${s} but signing_key is ZERO on chain! " "Key was blanked due to too many missed blocks. " "Send update_validator transaction to re-enable. head=#${h}", - ("w", scheduled_witness)("s", slot)("h", db.head_block_num())); + ("w", scheduled_validator)("s", slot)("h", db.head_block_num())); } } return block_validation_condition::not_my_turn; @@ -1802,15 +1802,15 @@ namespace graphene { auto private_key_itr = _private_keys.find(scheduled_key); if (private_key_itr == _private_keys.end()) { - capture("scheduled_validator", scheduled_witness); + capture("scheduled_validator", scheduled_validator); capture("scheduled_key", scheduled_key); return block_validation_condition::no_private_key; } // Pre-HF12 participation check (legacy behavior) if (!db.has_hardfork(CHAIN_HARDFORK_12)) { - uint32_t prate = db.witness_participation_rate(); - if (prate < _required_witness_participation) { + uint32_t prate = db.validator_participation_rate(); + if (prate < _required_validator_participation) { if (_production_skip_flags & graphene::chain::database::skip_undo_history_check) { dlog("Validator participation is ${p}% but stale-production is enabled, " "producing anyway to recover stalled network", @@ -1832,7 +1832,7 @@ namespace graphene { wlog("Block production LAG: our slot for ${w} at ${st} but now=${now} " "(delta=${d}ms). Production loop fired too late for this slot. " "head=#${h}", - ("w", scheduled_witness)("st", scheduled_time)("now", now) + ("w", scheduled_validator)("st", scheduled_time)("now", now) ("d", (scheduled_time - now).count() / 1000)("h", db.head_block_num())); } } @@ -1842,7 +1842,7 @@ namespace graphene { // Check if a competing block already exists in the fork database for this block height. // Two-level fork collision resolution: // Level 1: Vote-weighted comparison when both forks are in fork_db - // Level 2: Stuck-head timeout after one full witness round (21 blocks = 63s) + // Level 2: Stuck-head timeout after one full validator round (21 blocks = 63s) { auto existing_blocks = db.get_fork_db().fetch_block_by_number(db.head_block_num() + 1); if (existing_blocks.size() > 0) { @@ -1856,10 +1856,10 @@ namespace graphene { has_competing_block = true; competing_block = existing_blocks[0]; } else { - // Normal mode: only count blocks from different witnesses + // Normal mode: only count blocks from different validators // on a different parent as competing for (const auto &eb : existing_blocks) { - if (eb->data.validator != scheduled_witness && + if (eb->data.validator != scheduled_validator && eb->data.previous != db.head_block_id()) { has_competing_block = true; competing_block = eb; @@ -1874,8 +1874,8 @@ namespace graphene { // LEVEL 2: Stuck-head timeout // If we've been deferring and the head hasn't advanced, the competing // block is from a dead fork. The network has moved on without it. - // After 21 consecutive deferrals (one full witness round = 63s), - // we can be sure the longer chain had all scheduled witnesses + // After 21 consecutive deferrals (one full validator round = 63s), + // we can be sure the longer chain had all scheduled validators // produce on it — confirming it's the canonical chain. // This applies regardless of hardfork version — even pre-HF12 // nodes must not defer forever. @@ -1904,7 +1904,7 @@ namespace graphene { } else if (weight_cmp > 0) { // Competing fork has MORE vote weight // Defer to let the fork switch happen naturally via _push_block. - capture("height", db.head_block_num() + 1)("scheduled_witness", scheduled_witness); + capture("height", db.head_block_num() + 1)("scheduled_validator", scheduled_validator); wlog("Competing fork at height ${h} has more vote weight. " "Deferring to allow fork switch to stronger chain.", ("h", db.head_block_num() + 1)); @@ -1912,7 +1912,7 @@ namespace graphene { } else { // Tied or comparison impossible (one tip not in fork_db) // Defer briefly, timeout will kick in - capture("height", db.head_block_num() + 1)("scheduled_witness", scheduled_witness); + capture("height", db.head_block_num() + 1)("scheduled_validator", scheduled_validator); wlog("Fork collision at height ${h} with tied/unknown vote weight. " "Deferring (attempt ${n}/${max}).", ("h", db.head_block_num() + 1) @@ -1923,7 +1923,7 @@ namespace graphene { } // Pre-HF12: defer, but timeout still applies on next iteration else { - capture("height", db.head_block_num() + 1)("scheduled_witness", scheduled_witness); + capture("height", db.head_block_num() + 1)("scheduled_validator", scheduled_validator); wlog("Fork collision at height ${h} (pre-HF12). " "Deferring (attempt ${n}/${max}).", ("h", db.head_block_num() + 1) @@ -1965,8 +1965,8 @@ namespace graphene { } } catch (...) {} - if (db._debug_block_production) ilog("DEBUG_CRASH: calling generate_block for ${w}", ("w", scheduled_witness)); - if (scheduled_witness == CHAIN_EMERGENCY_VALIDATOR_ACCOUNT) { + if (db._debug_block_production) ilog("DEBUG_CRASH: calling generate_block for ${w}", ("w", scheduled_validator)); + if (scheduled_validator == CHAIN_EMERGENCY_VALIDATOR_ACCOUNT) { dlog("EMRG-DIAG producing: slot=${s} scheduled_time=${st} head=#${h} aslot=${a}", ("s", slot)("st", scheduled_time)("h", db.head_block_num()) ("a", db.get_dynamic_global_properties().current_aslot)); @@ -1978,11 +1978,11 @@ namespace graphene { // but in the future it should refactored to calling of a chain-plugin function auto block = db.generate_block( scheduled_time, - scheduled_witness, + scheduled_validator, private_key_itr->second, _production_skip_flags ); - capture("n", block.block_num())("t", block.timestamp)("c", now)("w", scheduled_witness)("tx", block.transactions.size()); + capture("n", block.block_num())("t", block.timestamp)("c", now)("w", scheduled_validator)("tx", block.transactions.size()); p2p().broadcast_block(block); // If we produced a block but have few/no peers, diff --git a/plugins/validator_api/plugin.cpp b/plugins/validator_api/plugin.cpp index 6b710173d7..1d979be9ab 100644 --- a/plugins/validator_api/plugin.cpp +++ b/plugins/validator_api/plugin.cpp @@ -182,24 +182,24 @@ std::set plugin::validator_plugin_impl::lookup_witness_accoun uint32_t limit ) const { FC_ASSERT(limit <= 1000); - const auto &witnesses_by_id = database.get_index().indices().get(); + const auto &validators_by_id = database.get_index().indices().get(); // get all the names and look them all up, sort them, then figure out what // records to return. This could be optimized, but we expect the - // number of witnesses to be few and the frequency of calls to be rare - std::set witnesses_by_account_name; - for (const auto& witness : witnesses_by_id) { + // number of validators to be few and the frequency of calls to be rare + std::set validators_by_account_name; + for (const auto& witness : validators_by_id) { if (witness.owner >= lower_bound_name) { // we can ignore anything below lower_bound_name - witnesses_by_account_name.insert(witness.owner); + validators_by_account_name.insert(witness.owner); } } - auto end_iter = witnesses_by_account_name.begin(); - while (end_iter != witnesses_by_account_name.end() && limit--) { + auto end_iter = validators_by_account_name.begin(); + while (end_iter != validators_by_account_name.end() && limit--) { ++end_iter; } - witnesses_by_account_name.erase(end_iter, witnesses_by_account_name.end()); - return witnesses_by_account_name; + validators_by_account_name.erase(end_iter, validators_by_account_name.end()); + return validators_by_account_name; } // Preferred-name aliases — forward to the legacy implementations above diff --git a/plugins/validator_guard/validator_guard.cpp b/plugins/validator_guard/validator_guard.cpp index b0f905b8ba..b38281fd92 100644 --- a/plugins/validator_guard/validator_guard.cpp +++ b/plugins/validator_guard/validator_guard.cpp @@ -36,61 +36,61 @@ struct validator_guard_plugin::impl { // ── config ──────────────────────────────────────────────────────────────── bool _enabled = true; uint32_t _check_interval = 20; // blocks between periodic checks - uint32_t _disable_threshold = 5; // consecutive blocks by same witness before auto-disable + uint32_t _disable_threshold = 5; // consecutive blocks by same validator before auto-disable bool _initial_check_done = false; // true once the node is confirmed in sync at startup - bool _stale_production_config = false; // mirrors enable-stale-production from witness config + bool _stale_production_config = false; // mirrors enable-stale-production from validator config boost::signals2::connection _applied_block_connection; // applied_block signal connection - // Per-witness consecutive block counter: witness_name -> count of consecutive blocks produced + // Per-validator consecutive block counter: validator_name -> count of consecutive blocks produced std::map _consecutive_blocks; - // Witnesses that have been auto-disabled and are awaiting manual intervention + // Validators that have been auto-disabled and are awaiting manual intervention // (we should NOT auto-restore them — only a restart or explicit action should re-enable) - std::set _auto_disabled_witnesses; + std::set _auto_disabled_validators; - // Per-witness key pair used for signing and for broadcasting the update - struct witness_info { + // Per-validator key pair used for signing and for broadcasting the update + struct validator_info { fc::ecc::private_key signing_key; fc::ecc::private_key active_key; }; - // Configured witnesses: witness_name -> key pair - std::map _witness_configs; + // Configured validators: validator_name -> key pair + std::map _validator_configs; - // Witnesses with an in-flight restore: witness_name -> tx expiration time + // validators with an in-flight restore: validator_name -> tx expiration time std::map _restore_pending; - // Transaction IDs awaiting block inclusion: tx_id -> (witness_name, expiration) + // Transaction IDs awaiting block inclusion: tx_id -> (validator_name, expiration) std::map> _pending_confirmations; // ── core ────────────────────────────────────────────────────────────────── bool check_and_restore_internal(); - void send_witness_update(const std::string& witness_name, + void send_validator_update(const std::string& validator_name, const graphene::chain::validator_object& obj, - const witness_info& config); - void send_witness_disable(const std::string& witness_name, + const validator_info& config); + void send_validator_disable(const std::string& validator_name, const graphene::chain::validator_object& obj, - const witness_info& config); + const validator_info& config); graphene::plugins::chain::plugin& chain_; graphene::plugins::p2p::p2p_plugin& p2p_; }; // ─── check_and_restore ─────────────────────────────────────────────────────── -// Checks all monitored witnesses and restores signing keys when needed. +// Checks all monitored validators and restores signing keys when needed. // Returns true if the node is in sync and the full check was performed. bool validator_guard_plugin::impl::check_and_restore_internal() { auto& database = db(); // Skip auto-restore when stale production is enabled AND the network is // not yet healthy. Once participation reaches >= 33% the stale-production - // override is no longer needed — auto-clear it (same logic as witness plugin) + // override is no longer needed — auto-clear it (same logic as validator plugin) // to remove operator human error and re-enable key restoration. if (_stale_production_config) { const auto& dgp = database.get_dynamic_global_properties(); if (!dgp.emergency_consensus_active) { - uint32_t prate = database.witness_participation_rate(); + uint32_t prate = database.validator_participation_rate(); if (prate >= 33 * CHAIN_1_PERCENT) { ilog("validator_guard: network is healthy (participation ${p}%), " "auto-clearing stale production override", @@ -147,11 +147,11 @@ bool validator_guard_plugin::impl::check_and_restore_internal() { static const graphene::protocol::public_key_type null_key; - // Iterate over configured witnesses and check their on-chain signing key. - // If a key is null, initiate a witness_update to restore it. - for (const auto& entry : _witness_configs) { + // Iterate over configured validators and check their on-chain signing key. + // If a key is null, initiate a validator_update to restore it. + for (const auto& entry : _validator_configs) { const std::string& name = entry.first; - const witness_info& config = entry.second; + const validator_info& config = entry.second; auto itr = idx.find(name); if (itr == idx.end()) { @@ -162,15 +162,15 @@ bool validator_guard_plugin::impl::check_and_restore_internal() { // Signing key is present on-chain — nothing to do if (itr->signing_key != null_key) { _restore_pending.erase(name); - // If this witness was auto-disabled and the key is now present on-chain, + // If this validator was auto-disabled and the key is now present on-chain, // clear the auto-disabled flag (operator must have manually restored) - _auto_disabled_witnesses.erase(name); + _auto_disabled_validators.erase(name); continue; } - // If this witness was auto-disabled by the consecutive-block guard, + // If this validator was auto-disabled by the consecutive-block guard, // do NOT auto-restore it — the operator must investigate and restart - if (_auto_disabled_witnesses.count(name)) { + if (_auto_disabled_validators.count(name)) { dlog("validator_guard: '${w}' was auto-disabled (consecutive block limit), " "skipping auto-restore", ("w", name)); continue; @@ -184,35 +184,35 @@ bool validator_guard_plugin::impl::check_and_restore_internal() { ilog("validator_guard: '${w}' has null signing key on-chain — initiating restore", ("w", name)); - send_witness_update(name, *itr, config); + send_validator_update(name, *itr, config); } return true; // node was in sync, full check performed } -// ─── send_witness_update ───────────────────────────────────────────────────── -// Builds, signs, and broadcasts a witness_update transaction that restores -// the on-chain signing key for the given witness. +// ─── send_validator_update ───────────────────────────────────────────────────── +// Builds, signs, and broadcasts a validator_update transaction that restores +// the on-chain signing key for the given validator. -void validator_guard_plugin::impl::send_witness_update( - const std::string& witness_name, +void validator_guard_plugin::impl::send_validator_update( + const std::string& validator_name, const graphene::chain::validator_object& obj, - const witness_info& config) + const validator_info& config) { try { const auto signing_pub = config.signing_key.get_public_key(); const auto& active_priv = config.active_key; - // Build the witness_update operation with the correct signing key + // Build the validator_update operation with the correct signing key graphene::protocol::validator_update_operation op; - op.owner = witness_name; + op.owner = validator_name; op.url = std::string(obj.url.begin(), obj.url.end()); op.block_signing_key = signing_pub; // 30-second expiration window for the transaction fc::time_point_sec expiration(graphene::time::now() + fc::seconds(30)); - // Assemble and sign the transaction with the witness's active authority key + // Assemble and sign the transaction with the validator's active authority key graphene::chain::signed_transaction tx; tx.operations.push_back(op); tx.set_expiration(expiration); @@ -228,47 +228,47 @@ void validator_guard_plugin::impl::send_witness_update( } ilog("validator_guard: broadcasting validator_update [ID: ${id}] for '${w}' — restoring key to ${k}", - ("id", tx_id)("w", witness_name)("k", signing_pub)); + ("id", tx_id)("w", validator_name)("k", signing_pub)); p2p_.broadcast_transaction(tx); // Track so we can confirm inclusion in a future block - _restore_pending[witness_name] = expiration; - _pending_confirmations[tx_id] = { witness_name, expiration }; + _restore_pending[validator_name] = expiration; + _pending_confirmations[tx_id] = { validator_name, expiration }; - ilog("validator_guard: validator_update for '${w}' sent successfully", ("w", witness_name)); + ilog("validator_guard: validator_update for '${w}' sent successfully", ("w", validator_name)); } catch (const fc::exception& e) { elog("validator_guard: validator_update FAILED for '${w}': ${e}", - ("w", witness_name)("e", e.to_detail_string())); + ("w", validator_name)("e", e.to_detail_string())); // Do not mark as pending — retry will happen on the next check cycle } } -// ─── send_witness_disable ───────────────────────────────────────────────────── -// Builds, signs, and broadcasts a witness_update transaction that sets the +// ─── send_validator_disable ───────────────────────────────────────────────────── +// Builds, signs, and broadcasts a validator_update transaction that sets the // on-chain signing key to null, effectively disabling block production. -void validator_guard_plugin::impl::send_witness_disable( - const std::string& witness_name, +void validator_guard_plugin::impl::send_validator_disable( + const std::string& validator_name, const graphene::chain::validator_object& obj, - const witness_info& config) + const validator_info& config) { try { const auto& active_priv = config.active_key; static const graphene::protocol::public_key_type null_key; - // Build the witness_update operation with null signing key to disable + // Build the validator_update operation with null signing key to disable graphene::protocol::validator_update_operation op; - op.owner = witness_name; + op.owner = validator_name; op.url = std::string(obj.url.begin(), obj.url.end()); op.block_signing_key = null_key; // 30-second expiration window for the transaction fc::time_point_sec expiration(graphene::time::now() + fc::seconds(30)); - // Assemble and sign the transaction with the witness's active authority key + // Assemble and sign the transaction with the validator's active authority key graphene::chain::signed_transaction tx; tx.operations.push_back(op); tx.set_expiration(expiration); @@ -278,18 +278,18 @@ void validator_guard_plugin::impl::send_witness_disable( const auto tx_id = tx.id(); ilog("validator_guard: broadcasting validator_update [ID: ${id}] for '${w}' — DISABLING (setting key to null)", - ("id", tx_id)("w", witness_name)); + ("id", tx_id)("w", validator_name)); p2p_.broadcast_transaction(tx); - // Mark this witness as auto-disabled so we don't auto-restore it - _auto_disabled_witnesses.insert(witness_name); + // Mark this validator as auto-disabled so we don't auto-restore it + _auto_disabled_validators.insert(validator_name); - ilog("validator_guard: validator_disable for '${w}' sent successfully", ("w", witness_name)); + ilog("validator_guard: validator_disable for '${w}' sent successfully", ("w", validator_name)); } catch (const fc::exception& e) { elog("validator_guard: validator_disable FAILED for '${w}': ${e}", - ("w", witness_name)("e", e.to_detail_string())); + ("w", validator_name)("e", e.to_detail_string())); } } @@ -419,7 +419,7 @@ void validator_guard_plugin::plugin_initialize( FC_ASSERT(sign_priv.valid(), "witness-guard-witness: invalid signing WIF for ${n}", ("n", name)); FC_ASSERT(active_priv.valid(), "witness-guard-witness: invalid active WIF for ${n}", ("n", name)); - pimpl->_witness_configs[name] = { *sign_priv, *active_priv }; + pimpl->_validator_configs[name] = { *sign_priv, *active_priv }; ilog("validator_guard: monitoring validator '${w}' (signing key: ${k})", ("w", name)("k", sign_priv->get_public_key())); @@ -431,13 +431,13 @@ void validator_guard_plugin::plugin_initialize( } } - if (pimpl->_witness_configs.empty()) { + if (pimpl->_validator_configs.empty()) { wlog("validator_guard: no validators configured for monitoring"); } ilog("validator_guard: plugin_initialize() end — " "monitoring ${n} validator(s), interval=${i} blocks", - ("n", pimpl->_witness_configs.size())("i", pimpl->_check_interval)); + ("n", pimpl->_validator_configs.size())("i", pimpl->_check_interval)); } FC_LOG_AND_RETHROW() } @@ -445,15 +445,15 @@ void validator_guard_plugin::plugin_initialize( void validator_guard_plugin::plugin_startup() { ilog("validator_guard: plugin_startup() begin"); - if (!pimpl->_enabled || pimpl->_witness_configs.empty()) { + if (!pimpl->_enabled || pimpl->_validator_configs.empty()) { ilog("validator_guard: nothing to monitor, plugin inactive"); return; } - // Verify on-chain authority for every configured witness. + // Verify on-chain authority for every configured validator // The chain database is open at this point so we can query account objects. - for (auto it = pimpl->_witness_configs.begin(); it != pimpl->_witness_configs.end(); ) { + for (auto it = pimpl->_validator_configs.begin(); it != pimpl->_validator_configs.end(); ) { const std::string& name = it->first; - const impl::witness_info& config = it->second; + const impl::validator_info& config = it->second; try { // VIZ stores authorities in account_authority_object (not account_object) @@ -474,11 +474,11 @@ void validator_guard_plugin::plugin_startup() { ++it; } catch (const fc::exception& e) { elog("validator_guard: account '${w}' not found on chain, removing from monitor list", ("w", name)); - it = pimpl->_witness_configs.erase(it); + it = pimpl->_validator_configs.erase(it); } } - if (pimpl->_witness_configs.empty()) return; + if (pimpl->_validator_configs.empty()) return; // Run an initial check at startup; mark done if the node is already in sync // (check_and_restore_internal returns true when the node is synchronized). @@ -492,39 +492,39 @@ void validator_guard_plugin::plugin_startup() { if (!pimpl->_enabled) return; // 0. Consecutive-block auto-disable check: - // If one of our witnesses produces N consecutive blocks, disable it. - if (pimpl->_disable_threshold > 0 && pimpl->_witness_configs.count(b.validator)) { + // If one of our validators produces N consecutive blocks, disable it. + if (pimpl->_disable_threshold > 0 && pimpl->_validator_configs.count(b.validator)) { const std::string& producer = b.validator; - // Reset counters for all OTHER witnesses — only the current producer's streak continues + // Reset counters for all OTHER validators — only the current producer's streak continues for (auto& entry : pimpl->_consecutive_blocks) { if (entry.first != producer) entry.second = 0; } - // Increment the consecutive counter for this witness + // Increment the consecutive counter for this validator pimpl->_consecutive_blocks[producer]++; const uint32_t count = pimpl->_consecutive_blocks[producer]; if (count >= pimpl->_disable_threshold) { // Already auto-disabled? Skip repeated broadcasts - if (!pimpl->_auto_disabled_witnesses.count(producer)) { + if (!pimpl->_auto_disabled_validators.count(producer)) { wlog("validator_guard: validator '${w}' produced ${c} consecutive blocks — " "auto-disabling (threshold=${t})", ("w", producer)("c", count)("t", pimpl->_disable_threshold)); - // Look up the witness object and send disable transaction + // Look up the validator object and send disable transaction const auto& idx = pimpl->db() .get_index() .indices() .get(); auto itr = idx.find(producer); if (itr != idx.end()) { - const auto& config = pimpl->_witness_configs.at(producer); - pimpl->send_witness_disable(producer, *itr, config); + const auto& config = pimpl->_validator_configs.at(producer); + pimpl->send_validator_disable(producer, *itr, config); } } } } else { - // Block produced by a different witness — reset ALL our consecutive counters + // Block produced by a different validator — reset ALL our consecutive counters // because the streak is broken if (!pimpl->_consecutive_blocks.empty()) { for (auto& entry : pimpl->_consecutive_blocks) { @@ -553,12 +553,12 @@ void validator_guard_plugin::plugin_startup() { } } - // 2. Look-ahead: if one of our witnesses is scheduled within the next 3 slots + // 2. Look-ahead: if one of our validators is scheduled within the next 3 slots // run an immediate check so the key is restored before the slot arrives bool scheduled_soon = false; if (pimpl->_initial_check_done) { for (uint32_t i = 1; i <= 3; ++i) { - if (pimpl->_witness_configs.count(pimpl->db().get_scheduled_validator(i))) { + if (pimpl->_validator_configs.count(pimpl->db().get_scheduled_validator(i))) { scheduled_soon = true; break; } @@ -566,7 +566,7 @@ void validator_guard_plugin::plugin_startup() { } // 3. Decide whether to run the periodic check: - // - scheduled_soon: one of our witnesses produces very soon + // - scheduled_soon: one of our validators produces very soon // - !_initial_check_done: keep probing every 10 blocks until the node syncs // - regular interval: every _check_interval blocks if (scheduled_soon) { diff --git a/programs/build_helpers/configure_build.py b/programs/build_helpers/configure_build.py index 03e51f5a4d..841ea3474f 100755 --- a/programs/build_helpers/configure_build.py +++ b/programs/build_helpers/configure_build.py @@ -76,13 +76,6 @@ def try_default_dir_from_env(args, flag_name, metavar_name, env_name=None): parser.add_argument("--openssl-dir", metavar="OPENSSL_ROOT", type=convert_to_dir, default=argparse.SUPPRESS, help="OpenSSL root directory (can alternatively specify with OPENSSL_ROOT_DIR environment variable)") - node_type = parser.add_mutually_exclusive_group() - node_type.add_argument("-f", "--full", dest="low_mem_node", - action="store_false", default=argparse.SUPPRESS, - help="build with LOW_MEMORY_NODE=OFF (default)") - node_type.add_argument("-w", "--witness", dest="low_mem_node", - action="store_true", default=argparse.SUPPRESS, - help="build with LOW_MEMORY_NODE=ON") build_type = parser.add_mutually_exclusive_group() build_type.add_argument("-r", "--release", dest="release", action="store_true", default=argparse.SUPPRESS, @@ -99,7 +92,7 @@ def try_default_dir_from_env(args, flag_name, metavar_name, env_name=None): parser.add_argument("additional_args", metavar="CMAKEOPTS", nargs=argparse.REMAINDER, help=argparse.SUPPRESS) - parser.set_defaults(low_mem_node=False, release=True, windows=False, + parser.set_defaults(release=True, windows=False, source_dir=src_default) parser.find_last_line_of_usage() @@ -178,8 +171,6 @@ def main(args): command.append("-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY") # Add Chain flags - command.append( - "-DLOW_MEMORY_NODE=" + ("ON" if args.low_mem_node else "OFF")) command.append( "-DCMAKE_BUILD_TYPE=" + ("RELEASE" if args.release else "DEBUG")) diff --git a/share/vizd/docker/Dockerfile-lowmem b/share/vizd/docker/Dockerfile-lowmem deleted file mode 100644 index 2f140cd98d..0000000000 --- a/share/vizd/docker/Dockerfile-lowmem +++ /dev/null @@ -1,82 +0,0 @@ -FROM phusion/baseimage:noble-1.0.3 AS builder - -ENV LANG=en_US.UTF-8 -ENV APPDIR /usr/local/src/viz/ -ENV HOME /var/lib/vizd - -RUN \ - apt-get update && \ - apt-get install -y --no-install-recommends \ - autoconf \ - automake \ - autotools-dev \ - binutils \ - bsdmainutils \ - build-essential \ - cmake \ - git \ - ccache \ - libboost-all-dev \ - libbz2-dev \ - liblzma-dev \ - libzstd-dev \ - libreadline-dev \ - libssl-dev \ - libtool \ - ncurses-dev \ - pbzip2 \ - pkg-config \ - zlib1g-dev && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -# Explicitly copy needed files to avoid re-building when changing other files -COPY .git $APPDIR/.git -COPY .gitignore .gitmodules CMakeLists.txt Doxyfile $APPDIR/ -COPY programs $APPDIR/programs -COPY thirdparty $APPDIR/thirdparty -COPY plugins $APPDIR/plugins -COPY libraries $APPDIR/libraries - -RUN \ - cd $APPDIR && \ - git submodule deinit -f . && \ - git submodule update --init --recursive -f && \ - sed -i '/add_subdirectory(tests)/d' thirdparty/fc/CMakeLists.txt && \ - mkdir build && \ - cd build && \ - cmake \ - -DCMAKE_BUILD_TYPE=Release \ - -DBUILD_SHARED_LIBRARIES=FALSE \ - -DLOW_MEMORY_NODE=TRUE \ - -DCHAINBASE_CHECK_LOCKING=FALSE \ - .. \ - && \ - make -j$(nproc) - -RUN set -xe ;\ - cd $APPDIR/build ;\ - make install ;\ - rm -rf $APPDIR - -FROM phusion/baseimage:noble-1.0.3 AS production -COPY --from=builder /usr/local /usr/local - -RUN set -xe ;\ - useradd -s /bin/bash -m -d /var/lib/vizd vizd ;\ - mkdir /var/cache/vizd ;\ - chown vizd:vizd -R /var/cache/vizd - -COPY share/vizd/vizd.sh /etc/service/vizd/run -COPY share/vizd/snapshot.json /var/lib/vizd -COPY share/vizd/config/config.ini /etc/vizd/config.ini - -# rpc services: -# http -EXPOSE 8090 -# ws -EXPOSE 8091 -# p2p service: -EXPOSE 2001 - -VOLUME ["/var/lib/vizd", "/etc/vizd"] diff --git a/share/vizd/docker/Dockerfile-production b/share/vizd/docker/Dockerfile-production index 82d40b2313..d32d7eec23 100644 --- a/share/vizd/docker/Dockerfile-production +++ b/share/vizd/docker/Dockerfile-production @@ -99,7 +99,6 @@ RUN --mount=type=cache,target=/root/.ccache,id=viz-ccache,sharing=locked \ cmake \ -DCMAKE_BUILD_TYPE=Release \ -DBUILD_SHARED_LIBRARIES=FALSE \ - -DLOW_MEMORY_NODE=FALSE \ -DCHAINBASE_CHECK_LOCKING=FALSE \ .. \ && \ diff --git a/share/vizd/docker/Dockerfile-testnet b/share/vizd/docker/Dockerfile-testnet index be7528f32b..f4ba3cc300 100644 --- a/share/vizd/docker/Dockerfile-testnet +++ b/share/vizd/docker/Dockerfile-testnet @@ -100,7 +100,6 @@ RUN --mount=type=cache,target=/root/.ccache,id=viz-ccache,sharing=locked \ -DCMAKE_BUILD_TYPE=Release \ -DBUILD_SHARED_LIBRARIES=FALSE \ -DBUILD_TESTNET=TRUE \ - -DLOW_MEMORY_NODE=FALSE \ -DCHAINBASE_CHECK_LOCKING=FALSE \ .. \ && \ diff --git a/thirdparty/appbase b/thirdparty/appbase index 3043bf51c6..caacf85b14 160000 --- a/thirdparty/appbase +++ b/thirdparty/appbase @@ -1 +1 @@ -Subproject commit 3043bf51c6d1e6b55effc7f048ddf16e32d3d627 +Subproject commit caacf85b14102cb616945877741846c263bc828d