Перейти до основного вмісту
Change page

Ethash

Останнє оновлення сторінки: 15 квітня 2026 р.

Ethash був алгоритмом майнінгу Ethereum на основі підтвердження роботи. Наразі підтвердження роботи повністю вимкнено, а Ethereum захищено за допомогою доказу частки. Дізнайтеся більше про The Merge, доказ частки та стейкінг. Ця сторінка лише для історичного інтересу!

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

Як працює Ethash?

Потужність пам'яті досягається за допомогою алгоритму підтвердження роботи, який вимагає вибору підмножин фіксованого ресурсу залежно від одноразового заголовка і блоку. Цей ресурс (розміром у кілька гігабайт) називається DAG. DAG змінюється кожні 30 000 блоків — вікно тривалістю ~125 годин, яке називається епохою (приблизно 5,2 дня), і генерується протягом певного часу. Оскільки DAG залежить лише від висоти блоку, його можна попередньо згенерувати, але якщо ні, клієнту потрібно дочекатися завершення цього процесу, щоб створити блок. Якщо клієнти не генерують і не кешують DAG заздалегідь, мережа може відчувати велику затримку блоку під час кожної зміни епохи. Зауважте, що DAG не потрібно створювати для перевірки підтвердження роботи, що, по суті, дозволяє проводити перевірку як із низьким рівнем ЦП, так і з невеликою пам’яттю.

Загальний маршрут, який використовує алгоритм, такий:

  1. Існує початкове значення, яке можна обчислити для кожного блоку шляхом сканування заголовків блоків до цього моменту.
  2. З початкового значення можна обчислити псевдовипадковий кеш розміром 16 МБ. Легкі клієнти зберігають кеш.
  3. З кешу ми можемо згенерувати набір даних розміром 1 ГБ з тією властивістю, що кожен елемент у наборі даних залежить лише від невеликої кількості елементів із кешу. Повні клієнти та майнери зберігають набір даних. Набір даних лінійно зростає з часом.
  4. Майнінг включає захоплення випадкових фрагментів набору даних і їх хешування разом. Перевірку можна виконати при малому обсязі пам’яті, використовуючи кеш для регенерації певних частин набору даних, які вам потрібні, тому вам потрібно лише зберігати кеш.

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

Визначення

Ми використовуємо такі визначення:

Використання SHA3

Розробка Ethereum збіглася в часі з розробкою стандарту SHA3, і в процесі стандартизації було внесено пізню зміну в доповнення фіналізованого хеш-алгоритму, тому хеші 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

Зверніть увагу, що, хоча в Жовтій книзі 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", у якому ми агрегуємо дані з повного набору даних, щоб отримати наше кінцеве значення для певного заголовка та nonce. У наведеному нижче коді header представляє хеш SHA3-256 RLP-представлення скороченого заголовка блоку, тобто заголовка, що не містить полів mixHash і nonce. nonce — це вісім байтів 64-бітного беззнакового цілого числа в порядку від старшого до молодшого. Отже, nonce[::-1] — це восьмибайтове представлення цього значення в порядку від молодшого до старшого:

По суті, ми підтримуємо "суміш" шириною 128 байтів і багаторазово послідовно вибираємо 128 байтів із повного набору даних та використовуємо функцію fnv для їхнього об'єднання із сумішшю. Використовується 128 байтів послідовного доступу, щоб кожен раунд алгоритму завжди отримував повну сторінку з ОЗП, мінімізуючи промахи буфера асоціативної трансляції, яких теоретично могли б уникнути ASIC.

Якщо результат цього алгоритму нижчий за бажану ціль, то nonce є дійсним. Зауважте, що додаткове застосування sha3_256 наприкінці гарантує, що існує проміжний nonce, який може бути наданий для доказу того, що було виконано принаймні невеликий обсяг роботи; ця швидка зовнішня PoW-перевірка може використовуватися для цілей захисту від DDoS. Це також служить для надання статистичної гарантії того, що результат є незміщеним 256-бітним числом.

Майнінг

Алгоритм майнінгу визначається таким чином:

def mine(full_size, dataset, header, difficulty):
    # zero-pad target to compare with hash on the same digit
    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 табульованих епох розмірів даних і розмірів кешу.

Ця стаття була корисною?