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

Этхэш

Этхэш был алгоритмом майнинга Эфириума на основе доказательства выполнения работы (PoW). Доказательство выполнения работы теперь полностью отключено, и безопасность Эфириума обеспечивается с помощью доказательства доли владения (PoS). Узнайте больше о Слиянии, доказательстве доли владения и стейкинге. Эта страница представляет лишь исторический интерес!

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

Как работает Этхэш?

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

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

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

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

Определения

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

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

Разработка Эфириума совпала с разработкой стандарта SHA3, и в процессе стандартизации было внесено позднее изменение в заполнение финализированного алгоритма хеширования, поэтому хеши Эфириума "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" упоминаются в описании алгоритма ниже.

Параметры

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

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

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

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

Процесс создания кеша включает в себя сначала последовательное заполнение 32 МБ памяти, а затем выполнение двух проходов алгоритма Серхио Демиана Лернера (Sergio Demian Lerner) RandMemoHash из Strict Memory Hard Hashing Functions (2014) (opens in a new tab). На выходе получается набор из 524288 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

Обратите внимание, что даже желтая книга определяет 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-битного целого числа без знака, где используется прямой порядок байтов. Таким образом, nonce[::-1] — это восьмибайтовое представление этого значения с обратным порядком байтов:

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

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

Майнинг

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

def mine(full_size, dataset, header, difficulty):
    # дополнить цель нулями для сравнения с хешем по тому же разряду
    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 сведенных в таблицу эпох размеров данных и размеров кеша.