Доказательство работы
Epic запускает три алгоритма доказательства работы на одной цепочке одновременно, в пропорции, закреплённой консенсусом. Каждый блок объявляет, каким алгоритмом он произведён. Все три всегда действительны в заданных пропорциях, а не заменяют друг друга при форке.
Три алгоритма
| Алгоритм | Узкое место | Минимальная сложность |
|---|---|---|
| Cuckoo / Cuckatoo | Поиск цикла в графе с ограничением по памяти | 3 |
| RandomX | CPU | 4,000 |
| ProgPow | GPU | 200,000 |
Параметры Cuckoo: размер доказательства 42, минимальное количество битов рёбер 19, количество битов рёбер второго доказательства работы 31, базовое количество битов рёбер 24.
Реализации алгоритмов находятся в отдельных крейтах: EpicCash/randomx-rust и EpicCash/progpow-rust.
Сложность отслеживается отдельно для каждого алгоритма, поэтому get_status возвращает tip.total_difficulty как объект с
одним u64 на алгоритм, с ключами cuckaroo, cuckatoo, randomx и progpow.
Заголовок блока указывает алгоритм в proof и содержит решение в solution — значении с внешней тегировкой,
форма которого зависит от этого алгоритма:
"proof": "Cuckoo" "solution": {"Cuckoo": [<u64>, ...]} 42 nonces
"proof": "RandomX" "solution": {"RandomX": "<decimal string>"} 32-byte hash, base 10
"proof": "ProgPow" "solution": {"ProgPow": [<byte>, ...]} 32-byte mix, one number per byte
"proof": "MD5" "solution": {"MD5": "<string>"} not scheduled on mainnet
Блоки Cuckatoo и Cuckaroo оба сообщают Cuckoo в proof и различаются по количеству битов рёбер. Типы
находятся в api/src/types.rs:574.
Политика блоков
Алгоритм, который должен использоваться для следующего блока, определяется детерминированной политикой. Реализация ведёт счётчик для каждого алгоритма и выбирает тот, который больше всего отстаёт от своей доли в текущем окне из 100 блоков, поэтому смесь в пределах окна точная, а не усреднённая.
Доли на 100 блоков:
| Эра | RandomX | ProgPow | Cuckatoo | Cuckaroo |
|---|---|---|---|---|
| Эры 1–2 | 60 | 38 | 2 | 0 |
| Эра 3 и далее | 48 | 48 | 4 | 0 |
Cuckaroo на mainnet получает нулевую долю. Он существует в системе типов и не планируется.
Политика скомпилирована в узел и не настраивается через epic-server.toml на mainnet. Два ключа сужают её в
тестовой сети:
[server]
only_randomx = true # каждый блок должен быть RandomX
no_progpow = false # или просто исключить ProgPow из смеси
only_randomx = true позволяет одному CPU-майнеру продвигать приватную цепочку: при смешанной политике майнер,
работающий только на RandomX, простаивает на каждой высоте ProgPow. Оба ключа изменяют политику
блоков, поэтому цепочка, намайненная с одной настройкой, недействительна с другой. Удалите chain_data при
изменении любого из них.
Доли mainnet находятся в core/src/core/block/feijoada.rs:249,
next_block_bottles()
продвигает окно и сбрасывает его на 100 блоках, choose_algo() выполняет выбор по PolicyConfig, а get_bottles_default() возвращает
обнулённые счётчики, с которых начинается каждое окно. Константы находятся в core/src/consensus.rs.
Сложность
Каждый алгоритм имеет собственный трек сложности, ретаргетируемый независимо через next_difficulty(). Окно
корректировки составляет 60 блоков (DIFFICULTY_ADJUST_WINDOW), один час при целевом интервале 60 секунд, и окно
проходит только по блокам того же алгоритма, поэтому каждый трек видит свою собственную историю.
Все три трека используют одинаковый коэффициент зажима 2 и коэффициент демпфирования 3.
Изменения консенсуса по высоте блока
Два изменения консенсуса привязаны к высотам блоков mainnet, а не к версионному форку:
| Высота | Изменение |
|---|---|
| 501,160 | Правило сложности меняется, минимумы RandomX и ProgPow переходят с 5,000 и 100,000 на 4,000 и 200,000 |
| 880,000 | Коэффициент истечения веса графа меняется: с одного года до ста лет блоков |
Реализация, учитывающая только объявленные версии форков, расходится на обоих. Первая объявленная высота хард-форка — 9,000,000, что при блоках с интервалом 60 секунд составляет более десяти лет, поэтому более поздние версии заголовков достижимы только в тестовых сетях.
Далее
Майнер подключается через Stratum на порту 3416 — сырой TCP с JSON, разделённым символами новой
строки, — или через внешний JSON-RPC интерфейс узла с помощью get_block_template, finalize_block_template и submit_block. EpicCash/epic-miner — эталонный
клиент для майнинга.