Выбор ветви и накопленная сложность
Иногда две версии цепочки какое-то время конкурируют, например когда сеть на несколько минут разделяется. Тогда каждый узел ZooBC следует ветви с большей накопленной сложностью — нарастающим итогом весов блоков, в котором блок от производителя, выбранного раньше, весит больше, чем блок от позднего. Правило — одна и та же арифметика на каждом узле, поэтому сеть сходится без того, чтобы кто-то выбирал победителя.
Тяжелее, а не длиннее
Каждый блок добавляет к нарастающему итогу величину, которая уменьшается тем сильнее, чем ниже в жеребьёвке этой высоты стоял его производитель. В простейшем виде блок добавляет 1 000 000, делённый на номер производителя в жеребьёвке: блок от первого выбранного производителя добавляет 1 000 000, от третьего — около 333 333.
Поэтому цепочка своевременных блоков перевешивает цепочку, производители которой то и дело пропускали свои ходы, даже если вторая длиннее. Три блока первого раунда весят 3 000 000; четыре блока третьего раунда — около 1 333 332.
Альтернативы не сработали бы. Подсчёт транзакций позволил бы производителю раздуть свой блок, чтобы победить. «Кто увиден первым» у каждого узла своё из-за сетевых задержек, поэтому узлы могли бы остаться разделёнными навсегда. И нет никакого органа, который объявлял бы ветвь официальной.
Точный вес блока
Начиная с версии 0.5.8 приращение блока равно:
increment = floor(1,000,000 × |S| / (k × |A|))
- S — набор жеребьёвки на момент предыдущего блока: активные узлы за вычетом приостановленных.
- A — весь активный реестр на момент предыдущего блока. Доля |S| / |A| никогда не превышает 1.
- k — число жребиев до последнего появления производителя в раундах вплоть до раунда блока: 1 для первого выбранного производителя, поставившего метку вовремя, 3 для производителя, названного третьим жребием. (Если производитель там не найден, используется его первое появление в пределах 2 × n жребиев, где n — число узлов в наборе жеребьёвки, а если и его нет — позиция в порядке хешей.)
Две нижние границы не позволяют блоку претендовать на больший вес, чем он заслуживает. k никогда не меньше раунда, в который попадает метка времени блока, поэтому поздняя метка не может сохранить вес раннего раунда (см. Раунды, время и окна). А для производителя предыдущего блока k никогда не меньше его пониженного раунда, 10 (см. Приоритетные раунды, пустые блоки и предыдущий производитель).
Доля набора жеребьёвки важна, когда сеть разделяется. Если каждая сторона разделения приостанавливает узлы, которых не слышит, то без этой доли обе стороны добавляли бы по 1 000 000 за своевременный блок и казались бы одинаково тяжёлыми. С долей сторона, работающая на 3 из 11 мест, добавляет не больше 272 727 за блок против 727 272 у стороны с 8 местами. Блок за блоком сторона, у которой больше мест, оказывается тяжелее.
Каждый блок несёт свою накопленную сложность в виде десятичной строки. Каждый валидатор пересчитывает её и отклоняет блок, в котором она указана неверно. Два итога сравниваются сначала по длине, затем цифра за цифрой.
Оценка участия во всём этом не участвует: вес учитывает позиции в жеребьёвке и набор жеребьёвки, а не оценки.
Точное равенство
Точное равенство случается, например, когда две ветви одинаковой длины обе состоят из своевременных блоков первого раунда. Начиная с версии 0.5.8 хеши вершинных блоков двух ветвей сравниваются как байты, и побеждает меньший хеш. Узел переключается на ветвь равного веса, хеш вершины которой меньше его собственного, иначе оставляет свою — и никого не спрашивает. Каждый узел применяет одно и то же сравнение к одним и тем же двум хешам, поэтому вся сеть сходится сразу.
Взвешивание ветви перед переключением
Утверждение пира, что его ветвь тяжелее, само по себе ничего не доказывает. Узел взвешивает конкурирующую ветвь, прежде чем трогать собственную цепочку:
- Он находит последний блок, общий для двух цепочек.
- Он загружает ветвь после этого блока постранично, проверяя подпись каждого заголовка и связи между блоками.
- Он пересчитывает вес каждого блока, воспроизводя собственный реестр и приостановки этой ветви начиная с общего блока, поскольку по другую сторону разделения они могут отличаться.
- Он останавливается, как только ветвь становится тяжелее его собственной цепочки, и только тогда откатывается и применяет её. Ветвь, которая в итоге оказывается легче или не обгоняет его цепочку за ограниченное число блоков, отклоняется, и ничего не откатывается.
Пир, заявленная сложность которого отличается от пересчитанной, отмечается как солгавший.
У откатов есть жёсткие пределы: никогда больше 720 блоков (3 часа) в mainnet и никогда ниже последней контрольной точки, соподписанной в spine-цепочке. См. Финальность и откат.
Отставшие узлы и опросы пиров
Узел, вершина которого старше 7 200 секунд (2 часа), не доверяет первому попавшемуся пиру, утверждающему, что он впереди: он следует вершине, о которой сообщают как минимум две трети выборки зарегистрированных пиров. Другие опросы пиров, которые узел может проводить, чтобы подтвердить более тяжёлую ветвь или проверить своё состояние, — локальная политика, а не консенсус.