Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
117 commits
Select commit Hold shift + click to select a range
15541b7
docs: add --restart unless-stopped to quick-start docker run examples
On1x Oct 16, 2026
45ee433
PM: freeze the no-contest fee at announcement (HF16, 4.2.0)
On1x Oct 19, 2026
3080ddb
Add node_admin plugin: loopback admin API with bearer tokens (read-on…
On1x Oct 19, 2026
9ea60fe
node_admin: serve MCP over the admin listener
On1x Oct 19, 2026
6ca9602
node_admin: P2P status and peer actions, built-in /ui/ page
On1x Oct 19, 2026
e09b7a7
node_admin: snapshot status, creation, download and in-process restore
On1x Oct 19, 2026
bed8ea8
webserver: per-IP stats, rate limits and IP lists managed via node_admin
On1x Oct 19, 2026
ae38327
node_admin: extract pure helpers and cover them with a CTest unit test
On1x Oct 19, 2026
3a3b0b3
node_admin: two-phase config/plugin edits and supervised restart
On1x Oct 19, 2026
8772934
node_admin: manage validator signing keys through validator_guard
On1x Oct 19, 2026
689b763
node_admin: add live E2E for validator guard operator paths
On1x Oct 19, 2026
604747e
validator: sign a block with the signing key committed at head
On1x Oct 19, 2026
320121f
Fix stale comment on why the E2E batch avoids the producing validator
On1x Oct 19, 2026
06cfe46
node_admin: let the built-in UI live behind a reverse-proxy prefix
On1x Oct 19, 2026
4d073af
fix(node_admin): include fc asio compat shim before websocketpp
On1x Oct 19, 2026
f027a93
ci(tests): discover test suites instead of naming two
On1x Oct 19, 2026
a11af66
node_admin: operator UI with tabs, scopes, paginated snapshots and li…
On1x Oct 19, 2026
24497a8
docs(node_admin): document auth.me, log listing, snapshot paging and …
On1x Oct 19, 2026
98f790d
node_admin: keep the log tail on tab switch and stop snapshot paging …
On1x Oct 19, 2026
130cd84
docs(node_admin): show the section form for the log appender and note…
On1x Oct 19, 2026
143af3e
node_admin: page the snapshot list by name cursor, not by shifting of…
On1x Oct 19, 2026
f1e8a5c
logging: optional line-capped file appender
On1x Oct 20, 2026
6627382
docs(node-admin): log file is bounded by time, not size
On1x Oct 20, 2026
f18d8ea
docs: hourly log rotation does not fire in vizd
On1x Oct 20, 2026
334990a
fix(logging): count capped-file lines by streaming, not by slurping t…
On1x Oct 20, 2026
45c6ac1
docs: state the capped appender's rollout and failure behaviour
On1x Oct 20, 2026
410c1b5
ci: note that pm-tests is a subset of tests.yml
On1x Oct 20, 2026
8735d0a
node_admin: edit logging settings, expose params per plugin
On1x Oct 20, 2026
38345c0
node_admin docs: per-plugin params, allow-list view, sectioned loggin…
On1x Oct 20, 2026
e999138
node_admin UI: plugins tab with parameter and logging panels, restart…
On1x Oct 20, 2026
ef5db25
node_admin: per-plugin status and an Objects tab with chainbase check…
On1x Oct 20, 2026
f767c65
node_admin: move the objects verdict into a tested header
On1x Oct 20, 2026
0811972
node_admin: cover plugin status and the objects judgement in live acc…
On1x Oct 20, 2026
9ec2fbf
node_admin: group p2p parameters by their real prefix
On1x Oct 20, 2026
4a37c73
node_admin: report the repair effect the node will actually perform
On1x Oct 20, 2026
3ffb347
node_admin: unit-test the repair effect text
On1x Oct 20, 2026
ad9b3ea
node_admin: acceptance covers a real repair, not only its refusals
On1x Oct 20, 2026
5b8ceed
node_admin: read plugin names the way the loader does
On1x Oct 20, 2026
d7468da
node_admin: end config values where the loader ends them
On1x Oct 20, 2026
3a499cb
node_admin: repair clears the marker that would outrank the chosen mode
On1x Oct 20, 2026
dd16c87
node_admin: read the state files where the chain writes them
On1x Oct 20, 2026
b786207
node_admin: acceptance against the real state layout and this user
On1x Oct 20, 2026
b515462
node_admin tests: CRLF fixture must match the split_lines contract
On1x Oct 20, 2026
51b8bec
node_admin UI: link each plugin to its documentation on GitHub Pages
On1x Oct 20, 2026
b6a7a60
node_admin UI: per-plugin panel with Status and Parameters
On1x Oct 20, 2026
d6e3c40
node_admin UI: keep lifecycle line and method in the plugin status box
On1x Oct 20, 2026
146ee73
HF16: activate on 2026-10-31 00:00:00 UTC
On1x Oct 20, 2026
1c224c8
protocol: name the 20-byte ids honestly; document how ids are computed
On1x Oct 20, 2026
ce998f0
validator: never sign post-validation for two block ids at one height
On1x Oct 20, 2026
3342616
p2p: gossip signed block votes and tally quorum certificates (QC step 0)
On1x Oct 20, 2026
b753b2a
chain: advance LIB from quorum certificates under HF16 (QC step 1)
On1x Oct 20, 2026
d84c3bf
consensus: handoff blocks carry the parent's QC under HF16 (QC step 2)
On1x Oct 20, 2026
3f09a65
chain: QC-based LIB uses 2-chain finality (QC step 1b)
On1x Oct 20, 2026
0d2bb45
chain: QC commit rule requires consecutive rounds (Jolteon 2-chain)
On1x Oct 21, 2026
a41dbe1
validator: Jolteon voting rule - one vote per round, round = slot (QC…
On1x Oct 21, 2026
a27dff3
consensus: every block carries its parent's QC under HF16 (QC step 3b)
On1x Oct 21, 2026
91c72e6
consensus: HF16 fork choice prefers the later certificate round (QC s…
On1x Oct 21, 2026
4cc99be
consensus_sim: producer self-votes under HF16 so the next block has a…
On1x Oct 21, 2026
3a5e19a
consensus_sim: vote for head before producing under HF16
On1x Oct 21, 2026
57c4acf
consensus_sim: every scheduled validator votes for head under HF16
On1x Oct 21, 2026
0bf112f
chain: accept votes for head even when classic LIB already reached it
On1x Oct 21, 2026
9c28fa8
protocol: timeout certificate wire type (HF16 step 2a)
On1x Oct 21, 2026
1f881d6
chain: tally timeout votes into timeout certificates (HF16 step 2b, c…
On1x Oct 21, 2026
808664b
testnet: CHAIN_TESTNET_VALIDATORS build knob for a multi-validator ne…
On1x Oct 21, 2026
a2c433c
p2p: gossip HF16 timeout votes (dlt_timeout_vote_message, type 5118)
On1x Oct 21, 2026
b2e883e
validator: send HF16 timeout votes when head stays without a QC
On1x Oct 21, 2026
00faa0d
chain: validate HF16 timeout certificates in block headers
On1x Oct 21, 2026
447d72a
chain: accept the timeout certificate in process_header_extensions
On1x Oct 21, 2026
2020a72
validator: build past a QC-less head with a timeout certificate (HF16)
On1x Oct 21, 2026
e45f9d3
validator: Jolteon voting rule and timeouts for empty rounds (HF16)
On1x Oct 21, 2026
361b791
HF16: late-QC fallback so a slow quorum costs finality, not the slot
On1x Oct 21, 2026
93d820c
HF16: punish double votes from a proof in the block header
On1x Oct 21, 2026
43a262e
HF16: record slot-switch time and add block_interval()/round_of()
On1x Oct 21, 2026
7bcd195
HF16: block_interval() reads has_hardfork(CHAIN_HARDFORK_16)
On1x Oct 21, 2026
e66e571
HF16: compute QC/TC rounds with round_of(), slot gaps with block_inte…
On1x Oct 21, 2026
d303902
HF16: keep hourly/committee cadence and PM reveal deadline in wall time
On1x Oct 21, 2026
6c848ef
HF16: bandwidth capacity and validator_guard freshness use block_inte…
On1x Oct 21, 2026
5141d29
HF16: get_config reports the live CHAIN_BLOCK_INTERVAL
On1x Oct 21, 2026
20777e9
consensus_sim: derive vote rounds and slot keys with round_of()
On1x Oct 21, 2026
7106a8c
HF16: scale block-denominated chain props x3 at the fork block
On1x Oct 21, 2026
a16abd1
HF16: replace one-off switch time with a reusable round anchor
On1x Oct 21, 2026
283c824
HF16: allow year-long block periods at 1 s, keep old bound until the …
On1x Oct 21, 2026
34772b4
ci: build the 21-validator testnet image for the pm PR
On1x Oct 21, 2026
3fb318c
dlt p2p: an empty node accepts peers that serve the chain from genesis
On1x Oct 21, 2026
b86e38f
p2p: serve irreversible blocks from block_log on non-DLT nodes
On1x Oct 21, 2026
dc5dc9a
fork_db: fill a data-less anchor when the real block arrives
On1x Oct 21, 2026
f36ea42
HF16: child of the activation block needs no parent QC
On1x Oct 21, 2026
0041baf
HF16: log why no vote is cast or accepted for head (once per block)
On1x Oct 21, 2026
69046ac
HF16: on a TC, rebuild the anchor's child instead of stalling on it
On1x Oct 21, 2026
0fd61f7
QC: bound timeout votes ahead of the wall-clock round, not head's
On1x Oct 22, 2026
a7011b1
QC: log once per head why a TC skip of a QC-less head is refused
On1x Oct 22, 2026
9126662
QC-LIB: 2-chain commit compares rounds, not a 3 s timestamp step
On1x Oct 22, 2026
f3c4fbf
HF16: a same-height sibling proving a later round becomes the fork ca…
On1x Oct 22, 2026
3ab688d
QC: after a TC, rebuild on the certified block below a late-QC head
On1x Oct 22, 2026
12a42dd
QC: a timeout vote reports the QC head carries, not its TC round
On1x Oct 22, 2026
279c4da
HF16: back off timeout votes for a QC-less head (pacemaker, Q#3123=A)
On1x Oct 22, 2026
ff7eb80
chain: reject a block before the first slot instead of wrapping misse…
On1x Oct 22, 2026
047fdc9
HF16: skip fork-collision deferral outside emergency
On1x Oct 22, 2026
135a696
HF16 vote diagnostics: key refusal logs by block id, log timed-out ro…
On1x Oct 22, 2026
bd85d8a
HF16: keep the highest-round QC per height, not the first
On1x Oct 22, 2026
43d6673
QC: remember_block_qc keeps the highest-round QC per height
On1x Oct 22, 2026
65befd0
docs: validator_equivocation virtual op (106) in en/ru/zh
On1x Oct 22, 2026
6e7ed76
HF16: scale undo-history cap with the block interval
On1x Oct 22, 2026
2cedb97
consensus_sim: HF16 boundary test (1 s slot, round re-anchor, x3 props)
On1x Oct 22, 2026
fa88982
validator: re-gossip own block vote with backoff until a QC forms
On1x Oct 23, 2026
ca98f06
Retain LIB ancestors while applying deferred fork database chains
On1x Oct 23, 2026
c19ce50
Scale HF16 committee request ceiling with current supply
On1x Oct 24, 2026
73d7d4d
Document HF16 DAO consensus and node admin across all locales
On1x Oct 24, 2026
943507b
Address HF16 and operator API review findings
On1x Oct 24, 2026
04efa66
Validate native HF16 periods and exercise multi-validator finality
On1x Oct 24, 2026
ea3f03f
Validate property votes before modifying live validator objects
On1x Oct 24, 2026
d85bb62
Run HF16 regressions with one and two validator configurations
On1x Oct 24, 2026
2220be2
Keep BFT recovery fixtures stable until equivocation punishment
On1x Oct 24, 2026
57f99e7
Model timeout recovery with independent databases and live fee cadence
On1x Oct 24, 2026
89d38e1
Stream large snapshot downloads with bounded memory
On1x Oct 24, 2026
7359f33
Use portable timer cancellation with Boost 1.91
On1x Oct 24, 2026
b24de7d
Keep IP admission available at capacity and always run quorum CI
On1x Oct 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 23 additions & 55 deletions .github/workflows/docker-pr-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,19 @@ jobs:
cache-from: type=gha,scope=pr-${{ github.base_ref }}
cache-to: type=gha,scope=pr-${{ github.base_ref }},mode=max

# HF16 QC stand (#6618): 21-validator testnet image for the tc-netem bench. Only built
# for PRs from `pm`, where the QC work lives; other PRs skip it.
- uses: docker/build-push-action@v7
if: github.head_ref == 'pm'
with:
context: .
file: ./share/vizd/docker/Dockerfile-testnet
build-args: TESTNET_VALIDATORS=21
push: true
tags: vizblockchain/vizd:${{ steps.tag.outputs.value }}-testnet21
cache-from: type=gha,scope=pr-testnet21
cache-to: type=gha,scope=pr-testnet21,mode=max

# The Docker build above proves the top of the supported Boost range (1.91,
# from the vizblockchain/vizd:boost-base base image). The tree is also supposed to build
# against the 1.83 that Ubuntu 24.04 ships, and nothing else covers that end.
Expand Down Expand Up @@ -137,6 +150,16 @@ jobs:
# touching PM consensus math, evaluators, crons, or chain properties. Builds only the
# tests/pm targets (chain/protocol/fc compile as make-dependencies); the consensus_sim
# harness is configured by BUILD_CONSENSUS_TESTS but never built here.
#
# 2026-10-20: this job is now a SUBSET of tests.yml and is kept only as a fast manual
# run. tests.yml discovers every binary named by add_test (so it builds all six pm_*
# targets plus node_admin_util and capped_file_appender), configures with the same
# flags, and runs the whole ctest — a superset of `ctest -R '^pm_'` here. Measured:
# the six binaries below are all in tests.yml's list. It skips only docs-only PRs,
# where there is nothing to test. Missing coverage is therefore NOT pm-tests but
# check-boost-range (the only job that builds `vizd` itself on Boost 1.83) and
# testnet-config (the only job that runs consensus_sim against testnet constants).
# A skipped gate is not a passing gate: a PR with 0 labels reports these as skipped.
pm_tests:
name: PM unit tests (ctest)
runs-on: ubuntu-latest
Expand Down Expand Up @@ -182,58 +205,3 @@ jobs:
set -euo pipefail
cd build
ctest -R '^pm_' --output-on-failure

# No other job compiles the testnet configuration, and no other job runs the
# fork-gated PM regressions. tests/consensus_sim/scenarios/test_pm_audit_fixes.cpp
# is appended by CMake only under -DBUILD_TESTNET=TRUE (the scenarios there need
# HF14 to activate, which the single-validator fixture can only reach with testnet
# constants), while the default Docker build never passes that flag and pm_tests
# builds only the PM unit targets. Compiling alone would not be enough either: the
# hardfork registry is validated by asserts that fire when a node opens the
# database (last_hardfork <= CHAIN_NUM_HARDFORKS, _hardfork_versions[last] <=
# CHAIN_VERSION), so the simulator has to actually run. Gated on the
# `testnet-config` label because the consensus_sim link is heavy.
testnet_config:
name: Testnet config + consensus_sim
runs-on: ubuntu-latest
if: contains(github.event.pull_request.labels.*.name, 'testnet-config')
timeout-minutes: 120

steps:
- uses: actions/checkout@v6
with:
submodules: recursive

- name: Install distro Boost and build deps
# Runners fetch packages from azure.archive.ubuntu.com; when that mirror goes quiet
# apt keeps retrying it and the job hangs for hours instead of failing (seen
# 2026-08-19). Pin the canonical mirror, bound the wait, and cap the step.
timeout-minutes: 15
run: |
set -euo pipefail
sudo sed -i 's|azure.archive.ubuntu.com|archive.ubuntu.com|g' \
/etc/apt/apt-mirrors.txt /etc/apt/sources.list 2>/dev/null || true
apt="sudo apt-get -o Acquire::Retries=3 -o Acquire::http::Timeout=20 -o Acquire::https::Timeout=20"
$apt update
$apt install -y --no-install-recommends \
build-essential cmake libboost-all-dev libssl-dev \
libbz2-dev liblzma-dev libzstd-dev libreadline-dev \
libtool ncurses-dev pkg-config zlib1g-dev

- name: Configure and build the consensus simulator (testnet config)
run: |
set -euo pipefail
sed -i '/add_subdirectory(tests)/d' thirdparty/fc/CMakeLists.txt
mkdir -p build && cd build
cmake -DCMAKE_BUILD_TYPE=Release \
-DBUILD_SHARED_LIBRARIES=FALSE \
-DCHAINBASE_CHECK_LOCKING=FALSE \
-DBUILD_TESTNET=TRUE \
-DBUILD_CONSENSUS_TESTS=ON ..
make -j"$(nproc)" consensus_sim_tests

- name: Run the simulator
run: |
set -euo pipefail
cd build
ctest -R '^consensus_sim$' --output-on-failure
64 changes: 62 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,10 @@ jobs:
-DCHAINBASE_CHECK_LOCKING=FALSE \
-DBUILD_CONSENSUS_TESTS=ON ..
# Build exactly the binaries ctest will run, so a new add_test never shows up as "Not Run".
TEST_BINS=$(grep -ho 'add_test(NAME [a-z_]* COMMAND [a-z_]*' \
../tests/pm/CMakeLists.txt ../tests/consensus_sim/CMakeLists.txt | awk '{print $NF}')
# Discover the suites instead of naming them: a hardcoded list silently skipped
# tests/node_admin and ctest reported its only test as "Not Run".
TEST_CMAKE=$(find ../tests -mindepth 2 -maxdepth 2 -name CMakeLists.txt)
TEST_BINS=$(grep -ho 'add_test(NAME [a-z_]* COMMAND [a-z_]*' $TEST_CMAKE | awk '{print $NF}')
make -j"$(nproc)" $TEST_BINS

- name: Run tests
Expand All @@ -69,3 +71,61 @@ jobs:
name: consensus-sim-failures
path: tests/consensus_sim/failures/
if-no-files-found: ignore

# Mandatory on every code PR and master push: real two-signer BFT coverage
# must not depend on a label. The N=1 arm also covers fork-gated PM scenarios.
testnet_config:
name: Testnet config + consensus_sim (${{ matrix.validators }} validators)
strategy:
fail-fast: false
matrix:
validators: [1, 2]
runs-on: ubuntu-latest
timeout-minutes: 120

steps:
- uses: actions/checkout@v6
with:
submodules: recursive

- name: Install distro Boost and build deps
# Runners fetch packages from azure.archive.ubuntu.com; when that mirror goes quiet
# apt keeps retrying it and the job hangs for hours instead of failing (seen
# 2026-08-19). Pin the canonical mirror, bound the wait, and cap the step.
timeout-minutes: 15
run: |
set -euo pipefail
sudo sed -i 's|azure.archive.ubuntu.com|archive.ubuntu.com|g' \
/etc/apt/apt-mirrors.txt /etc/apt/sources.list 2>/dev/null || true
apt="sudo apt-get -o Acquire::Retries=3 -o Acquire::http::Timeout=20 -o Acquire::https::Timeout=20"
$apt update
$apt install -y --no-install-recommends \
build-essential cmake libboost-all-dev libssl-dev \
libbz2-dev liblzma-dev libzstd-dev libreadline-dev \
libtool ncurses-dev pkg-config zlib1g-dev

- name: Configure and build the consensus simulator (testnet config)
run: |
set -euo pipefail
sed -i '/add_subdirectory(tests)/d' thirdparty/fc/CMakeLists.txt
mkdir -p build && cd build
multi=()
if [ "${{ matrix.validators }}" = "2" ]; then
multi=(-DCHAIN_TESTNET_VALIDATORS=2)
fi
cmake -DCMAKE_BUILD_TYPE=Release \
-DBUILD_SHARED_LIBRARIES=FALSE \
-DCHAINBASE_CHECK_LOCKING=FALSE \
-DBUILD_TESTNET=TRUE \
-DBUILD_CONSENSUS_TESTS=ON "${multi[@]}" ..
make -j"$(nproc)" consensus_sim_tests

- name: Run the simulator
run: |
set -euo pipefail
cd build
if [ "${{ matrix.validators }}" = "2" ]; then
tests/consensus_sim/consensus_sim_tests --run_test=hf16_boundary_suite --log_level=test_suite
else
ctest -R '^consensus_sim$' --output-on-failure
fi
4 changes: 4 additions & 0 deletions @l10n/ru/docs/api/client-libraries.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,3 +225,7 @@ let shares = VIZ.Asset(1000.0, .vests) // "1000.000000 VESTS"
---

См. также: [JSON-RPC API](./json-rpc.md), [CLI Wallet](./cli-wallet.md).

## Совместимость с HF16

JS 0.18.5 опубликован в npm и поддерживает заголовки QC/TC/двойного голосования. PHP сохраняет формат транзакций и передаёт новый JSON заголовков. Исходники Python 1.4.0 и зависимости прошли CI Python 3.10–3.14; публикация PyPI отдельная. Клиенты DAO не должны хранить фиксированный потолок 500 000 VIZ: лимит проверяет нода от текущей эмиссии. См. [HF16](../consensus/hf16.md).
29 changes: 29 additions & 0 deletions @l10n/ru/docs/api/ids-and-hashes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Идентификаторы транзакций и блоков

Типы идентификаторов VIZ унаследовал от Graphene (BitShares, затем Steem). В исходниках они
объявлены как `fc::ripemd160`, и старая документация и библиотеки называют их «ripemd160 id». Это
только имя 20-байтового контейнера, в котором они хранятся: **ни один из этих id не является
ripemd160-хэшем.** Нода объявляет их через алиас `id160_type`, чтобы сказать это прямо.

| Значение | Как вычисляется | Размер |
|---|---|---|
| `transaction_id` | первые 20 байт `sha256(сериализованная транзакция)`, подписи **не** входят | 20 байт |
| `block_id` | первые 20 байт `sha224(сериализованный заголовок блока)`, затем байты 0–3 заменяются номером блока (big-endian) | 20 байт |
| `transaction_merkle_root` | `ripemd160` от корня sha256-дерева по подписанным транзакциям | 20 байт |

Merkle root — единственное значение, которое действительно ripemd160.

## Что это значит для клиентов

* Чтобы посчитать id транзакции, сериализуйте её **без** `signatures`, возьмите sha256 и оставьте
первые 20 байт. ripemd160 не применять — результат никогда не совпадёт с нодой.
* Номер блока читается прямо из block id: это первые 4 байта, big-endian. TaPoS
(`ref_block_num` / `ref_block_prefix`) берёт младшие 16 бит этого номера и байты 4–7 block id.
* Id имеют длину 20 байт во всех ответах API, в block log и в истории аккаунтов. Смена хэша (на
настоящий ripemd160 или на полный 32-байтовый sha256) была бы хардфорком, который делит историю на
два формата id, без выигрыша в безопасности: 160 бит для идентификатора достаточно, а подпись
ставится на полный sha256-дайджест, а не на id.

Исходники: `transaction::id()` в `libraries/protocol/transaction.cpp`, `signed_block_header::id()` и
`signed_block::calculate_merkle_root()` в `libraries/protocol/block.cpp`, типы — в
`libraries/protocol/include/graphene/protocol/types.hpp`.
4 changes: 4 additions & 0 deletions @l10n/ru/docs/consensus/block-processing.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Обработка блоков

> **HF16 / 4.2.0:** слот 1 секунда, QC/TC и правило 2-chain описаны в [HF16](./hf16.md). Старые описания 3 секунд и 14 подтверждений ниже относятся к прежнему режиму, а не к кворуму QC HF16.


Внутренняя механика применения блоков, управления ожидающими транзакциями и переключения форков.

---
Expand Down Expand Up @@ -298,6 +301,7 @@ struct block_post_validation_message {
### Ограничения

- В зачёт порога 2/3 идут только валидаторы из **текущего перетасованного расписания**; валидаторы вне расписания пропускаются.
- **Один голос на раунд (правило безопасности Jolteon).** Валидатор голосует за блок раунда *r* (раунд = слот блока, `timestamp / CHAIN_BLOCK_INTERVAL`), только если *r* выше самого старшего раунда, в котором он уже голосовал. Плагин валидатора хранит этот раунд для каждого валидатора в `<data-dir>/block-vote-round.txt`, записывает его **до** отправки голоса (голос, раунд которого не удалось сохранить, не отправляется) и пишет в лог `Not voting for … already voted for … in round …`, если в том же раунде появился другой блок. В отличие от правила «одна подпись на высоту», в более позднем раунде валидатор может проголосовать за другой блок той же высоты — именно это позволяет расколу голосов разрешиться, а не застрять. Два конфликтующих сертификата кворума в одном раунде требуют валидаторов, голосующих дважды; ноды пишут такие голоса в лог как `Equivocation: …`. Повторная рассылка того же голоса разрешена.
- Во время **аварийного консенсуса** (`emergency_consensus_active = true`) `check_block_post_validation_chain()` сразу возвращается — LIB продвигается исключительно по классическому пути, чтобы не заблокировать восстановление.
- Список подтверждений ограничен **20 записями** (`CHAIN_MAX_BLOCK_POST_VALIDATION_COUNT`). Записи ниже текущего LIB удаляются после каждого блока.

Expand Down
6 changes: 3 additions & 3 deletions @l10n/ru/docs/consensus/emergency-consensus.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# Режим экстренного консенсуса

Режим экстренного консенсуса (введён в HF12) активируется автоматически, когда сеть простаивает в течение 1 часа. Специальный валидатор "committee" берёт на себя производство блоков для поддержания непрерывности цепочки до тех пор, пока реальные валидаторы не восстановят свои ключи подписи.
Режим экстренного консенсуса (введён в HF12) активируется автоматически, когда сеть простаивает в течение 20 минут. Специальный валидатор "committee" берёт на себя производство блоков для поддержания непрерывности цепочки до тех пор, пока реальные валидаторы не восстановят свои ключи подписи.

---

## Ключевые константы

| Константа | Значение | Значение |
|-----------|---------|---------|
| `CHAIN_EMERGENCY_CONSENSUS_TIMEOUT_SEC` | 3600 с | Время простоя до активации |
| `CHAIN_EMERGENCY_CONSENSUS_TIMEOUT_SEC` | 1200 с | Время простоя до активации |
| `CHAIN_EMERGENCY_VALIDATOR_ACCOUNT` | `"committee"` | Аккаунт экстренного производителя блоков |
| `CHAIN_EMERGENCY_VALIDATOR_PUBLIC_KEY` | `VIZ75CR...` | Детерминированный ключ подписи для экстренного режима |
| `CHAIN_EMERGENCY_EXIT_NORMAL_BLOCKS` | 21 | Последовательные блоки реальных валидаторов для выхода |
Expand All @@ -31,7 +31,7 @@
1. **Ворота HF12** — пропустить, если харфорк ещё не активирован.
2. **Уже активен** — пропустить, если экстренный режим уже включён.
3. **LIB-блок доступен в block log** — пропустить, если LIB-блок отсутствует в block log (DLT-узлы после восстановления из снимка имеют пустой block log; отсутствие LIB-блока вычислило бы миллионы устаревших секунд и запустило бы ложный дедлок активации).
4. **Таймаут** — вычислить `seconds_since_lib = current_block.timestamp − lib_block.timestamp`. Если `< 3600`, пропустить.
4. **Таймаут** — вычислить `seconds_since_lib = current_block.timestamp − lib_block.timestamp`. Если `< 1200`, пропустить.

Все проверки используют только временны́е метки, встроенные в блоки — никаких системных часов, никаких флагов пропуска. Это гарантирует идентичную детерминированную активацию на каждом узле, включая воспроизведения.

Expand Down
5 changes: 4 additions & 1 deletion @l10n/ru/docs/consensus/fair-dpos.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Консенсус Fair-DPOS

> **HF16 / 4.2.0:** слот 1 секунда, QC/TC и правило 2-chain описаны в [HF16](./hf16.md). Старые описания 3 секунд и 14 подтверждений ниже относятся к прежнему режиму, а не к кворуму QC HF16.


VIZ Ledger использует **Fair Delegated Proof of Stake (Fair-DPOS)** — расширение классического алгоритма DPoS, добавляющее контроль участия и штрафы за пропуски блоков для предотвращения получения вознаграждений без реального производства.

---
Expand All @@ -9,7 +12,7 @@ VIZ Ledger использует **Fair Delegated Proof of Stake (Fair-DPOS)**
В стандартном DPoS:
- Держатели токенов голосуют за аккаунты-валидаторы (с весом, пропорциональным SHARES).
- Валидаторы с наибольшим числом голосов планируются для производства блоков в порядке round-robin.
- Каждые 3 секунды срабатывает один слот; запланированный валидатор либо производит блок, либо пропускает слот.
- Каждые 3 секунды до HF16 (1 секунду после активации) срабатывает один слот; запланированный валидатор либо производит блок, либо пропускает слот.

VIZ работает с **21 активным валидатором** в каждом раунде расписания.

Expand Down
Loading
Loading