Перейти к основному контенту
Change page

Ethash

Последнее обновление страницы: 15 апреля 2026 г.

Ethash был алгоритмом майнинга Ethereum с доказательством работы. Доказательство работы теперь полностью отключено, и Ethereum теперь защищен с помощью доказательства владения . Подробнее о Слиянии, доказательстве владения и стейкинге. В этой статье много чего интересного!

Ethash — это модифицированная версия алгоритма Dagger-Hashimoto. Алгоритм доказательства работы Ethash требователен к памяти (opens in a new tab), что, как считалось, делает его устойчивым к ASIC. В конечном итоге были разработаны Ethash ASIC, но майнинг на графическом процессоре все еще оставался жизнеспособным вариантом, пока не было отключено доказательство работы. Ethash по-прежнему используется для майнинга других монет в других не-Ethereum сетях доказательства работы.

Как работает Ethash?

Требовательность к памяти достигается с помощью алгоритма доказательства работы, который требует выбора подмножеств фиксированного ресурса в зависимости от нонса и заголовка блока. Этот ресурс (размером в несколько гигабайт) называется DAG. DAG изменяется каждые 30 000 блоков, то есть в ~125-часовое окно, называемое эпохой (примерно 5,2 дня), и для его генерации требуется некоторое время. Поскольку DAG зависит только от высоты блока, его можно сгенерировать заранее, но если этого не сделать, клиенту придется дождаться окончания этого процесса, чтобы создать блок. Если клиенты не генерируют и не кэшируют DAG заранее, в сети может возникнуть значительная задержка блоков при каждом переходе между эпохами. Обратите внимание, что DAG не нужно генерировать для проверки доказательства работы, что по сути позволяет проводить проверку при низкой загрузке ЦП и небольшом объеме памяти.

Общая схема работы алгоритма следующая:

  1. Существует начальное значение (сид), которое можно вычислить для каждого блока путем сканирования заголовков блоков до этого момента.
  2. Из сида можно вычислить псевдослучайный кэш размером 16 МБ. Легкие клиенты хранят кэш.
  3. Из кэша мы можем сгенерировать набор данных размером 1 ГБ со свойством, что каждый элемент в наборе данных зависит только от небольшого числа элементов из кэша. Полные клиенты и майнеры хранят набор данных. Набор данных растет линейно со временем.
  4. Майнинг включает в себя получение случайных срезов набора данных и их совместное хэширование. Проверку можно выполнить с небольшим объемом памяти, используя кэш для восстановления необходимых частей набора данных, поэтому вам нужно хранить только кэш.

Большой набор данных обновляется каждые 30 000 блоков, поэтому подавляющее большинство усилий майнера будет направлено на чтение набора данных, а не на внесение в него изменений.

Определения

Мы используем следующие определения:

Использование SHA3

Разработка Ethereum совпала с разработкой стандарта SHA3, и в процессе стандартизации в последний момент было внесено изменение в дополнение (padding) финального алгоритма хэширования, так что хэши Ethereum «sha3_256» и «sha3_512» не являются стандартными хэшами SHA3, а вариантом, который в других контекстах часто называют «Keccak-256» и «Keccak-512». См. обсуждение, например, здесь (opens in a new tab), здесь (opens in a new tab) или здесь (opens in a new tab).

Пожалуйста, имейте это в виду, поскольку хэши "sha3" упоминаются в описании алгоритма ниже.

Параметры

Параметры кэша и набора данных Ethash зависят от номера блока. Размеры кэша и набора данных растут линейно; однако мы всегда берем наибольшее простое число ниже линейно растущего порога, чтобы снизить риск случайных закономерностей, ведущих к циклическому поведению.

Таблицы со значениями размеров набора данных и кэша приведены в приложении.

Генерация кэша

Теперь мы определим функцию для создания кэша:

Процесс создания кэша включает в себя сначала последовательное заполнение 32 МБ памяти, а затем выполнение двух проходов алгоритма RandMemoHash Серджио Демиана Лернера из «Strict Memory Hard Hashing Functions» (2014) (opens in a new tab). Результатом является набор из 524 288 64-байтовых значений.

Функция агрегирования данных

В некоторых случаях мы используем алгоритм, вдохновленный хэшем FNV (opens in a new tab), в качестве неассоциативной замены для XOR. Обратите внимание, что мы умножаем простое число на полный 32-битный ввод, в отличие от спецификации FNV-1, которая поочередно умножает простое число на один байт (октет).

FNV_PRIME = 0x01000193

def fnv(v1, v2):
    return ((v1 * FNV_PRIME) ^ v2) % 2**32

Обратите внимание, что, хотя в Yellow Paper для fnv указано v1*(FNV_PRIME ^ v2), все текущие реализации последовательно используют приведенное выше определение.

Вычисление полного набора данных

Каждый 64-байтовый элемент в полном наборе данных размером 1 ГБ вычисляется следующим образом:

По сути, мы объединяем данные из 256 псевдослучайно выбранных узлов кэша и хэшируем их для вычисления узла набора данных. Затем весь набор данных генерируется с помощью:

def calc_dataset(full_size, cache):
    return [calc_dataset_item(cache, i) for i in range(full_size // HASH_BYTES)]

Основной цикл

Теперь мы опишем основной цикл, подобный «hashimoto», в котором мы агрегируем данные из полного набора данных, чтобы получить конечное значение для определенного заголовка и нонса. В приведенном ниже коде header представляет собой хэш SHA3-256 от RLP-представления усеченного заголовка блока, то есть заголовка, исключающего поля mixHash и nonce. nonce — это восемь байт 64-битного беззнакового целого числа в порядке от старшего к младшему (big-endian). Таким образом, nonce[::-1] — это восьмибайтовое представление этого значения в порядке от младшего к старшему (little-endian):

По сути, мы поддерживаем «mix» шириной 128 байт, и многократно последовательно извлекаем 128 байт из полного набора данных и используем функцию fnv для их объединения с mix. 128 байт последовательного доступа используются для того, чтобы каждый раунд алгоритма всегда извлекал полную страницу из ОЗУ, минимизируя промахи буфера ассоциативной трансляции (TLB), которых теоретически могли бы избежать ASIC.

Если результат работы этого алгоритма ниже желаемого целевого значения, то нонс считается действительным. Обратите внимание, что дополнительное применение sha3_256 в конце гарантирует существование промежуточного нонса, который можно предоставить для доказательства того, что была проделана хотя бы небольшая работа; эта быстрая внешняя проверка PoW может использоваться для защиты от DDoS-атак. Это также служит для статистической гарантии того, что результат является несмещенным 256-битным числом.

Майнинг

Алгоритм майнинга определяется следующим образом:

def mine(full_size, dataset, header, difficulty):
    # дополняем нулями target, чтобы сравнивать с хэшем одинаковой длины
    target = zpad(encode_int(2**256 // difficulty), 64)[::-1]
    from random import randint
    nonce = randint(0, 2**64)
    while hashimoto_full(full_size, dataset, header, nonce) > target:
        nonce = (nonce + 1) % 2**64
    return nonce

Определение хэша сида

Чтобы вычислить хэш сида, который будет использоваться для майнинга поверх данного блока, мы используем следующий алгоритм:

 def get_seedhash(block):
     s = '\x00' * 32
     for i in range(block.number // EPOCH_LENGTH):
         s = serialize_hash(sha3_256(s))
     return s

Обратите внимание, что для бесперебойного майнинга и проверки мы рекомендуем предварительно вычислять будущие хэши сидов и наборы данных в отдельном потоке.

Дополнительные материалы

Знаете ресурс сообщества, который вам пригодился? Измените эту страницу и добавьте его!

Приложение

Следующий код следует добавить в начало, если вы хотите запустить приведенную выше спецификацию на Python как код.

Размеры данных

Следующие справочные таблицы содержат примерно 2048 табличных эпох с размерами данных и кэша.

Была ли эта статья полезной?