Přejít na hlavní obsah
Change page

Ethash

Ethash byl těžební algoritmus Etherea založený na důkazu prací (PoW). Důkaz prací (PoW) byl nyní zcela vypnut a Ethereum je místo toho zabezpečeno pomocí důkazu podílem (PoS). Přečtěte si více o Merge, důkazu podílem (PoS) a stakingu. Tato stránka slouží pouze pro historické účely!

Ethash je upravená verze algoritmu Dagger-Hashimoto. Důkaz prací (PoW) Ethash je paměťově náročný (opens in a new tab), což mělo zajistit odolnost algoritmu vůči ASIC. ASIC pro Ethash byly nakonec vyvinuty, ale těžba pomocí GPU byla stále schůdnou možností, dokud nebyl důkaz prací (PoW) vypnut. Ethash se stále používá k těžbě jiných mincí na jiných sítích s důkazem prací (PoW) mimo Ethereum.

Jak Ethash funguje?

Paměťové náročnosti je dosaženo pomocí algoritmu důkazu prací (PoW), který vyžaduje výběr podmnožin pevného zdroje v závislosti na nonce a hlavičce bloku. Tento zdroj (o velikosti několika gigabajtů) se nazývá DAG. DAG se mění každých 30 000 bloků, což je okno o délce přibližně 125 hodin nazývané epocha (zhruba 5,2 dne), a jeho generování chvíli trvá. Vzhledem k tomu, že DAG závisí pouze na výšce bloku, může být předgenerován, ale pokud není, klient musí počkat na konec tohoto procesu, aby mohl vytvořit blok. Pokud klienti předem negenerují a neukládají DAG do mezipaměti, síť může při každém přechodu epochy zaznamenat masivní zpoždění bloků. Všimněte si, že DAG není nutné generovat pro ověření důkazu prací (PoW), což v podstatě umožňuje ověření s nízkým využitím CPU i malou pamětí.

Obecný postup algoritmu je následující:

  1. Existuje seed (semínko), které lze vypočítat pro každý blok prohledáním hlaviček bloků až do daného bodu.
  2. Ze seedu lze vypočítat 16 MB pseudonáhodnou mezipaměť (cache). Lehcí klienti (light clients) tuto mezipaměť ukládají.
  3. Z mezipaměti můžeme vygenerovat 1 GB datovou sadu (dataset) s tou vlastností, že každá položka v datové sadě závisí pouze na malém počtu položek z mezipaměti. Plní klienti (full clients) a těžaři tuto datovou sadu ukládají. Datová sada roste lineárně s časem.
  4. Těžba zahrnuje odebírání náhodných částí datové sady a jejich společné hashování. Ověření lze provést s nízkou pamětí pomocí mezipaměti k opětovnému vygenerování konkrétních částí datové sady, které potřebujete, takže stačí ukládat pouze mezipaměť.

Velká datová sada se aktualizuje jednou za 30 000 bloků, takže drtivá většina úsilí těžaře bude spočívat ve čtení datové sady, nikoli v jejích úpravách.

Definice

Používáme následující definice:

Použití 'SHA3'

Vývoj Etherea se časově shodoval s vývojem standardu SHA3 a proces standardizace provedl pozdní změnu ve výplni (padding) finalizovaného hashovacího algoritmu, takže hashe „sha3_256“ a „sha3_512“ v Ethereu nejsou standardní hashe sha3, ale varianta často označovaná v jiných kontextech jako „Keccak-256“ a „Keccak-512“. Viz diskuse, např. zde (opens in a new tab), zde (opens in a new tab) nebo zde (opens in a new tab).

Mějte to prosím na paměti, protože v níže uvedeném popisu algoritmu se odkazuje na hashe „sha3“.

Parametry

Parametry pro mezipaměť a datovou sadu Ethash závisí na čísle bloku. Velikost mezipaměti i velikost datové sady rostou lineárně; vždy však bereme nejvyšší prvočíslo pod lineárně rostoucí prahovou hodnotou, abychom snížili riziko náhodných pravidelností vedoucích k cyklickému chování.

Tabulky hodnot velikostí datové sady a mezipaměti jsou uvedeny v příloze.

Generování mezipaměti

Nyní specifikujeme funkci pro vytvoření mezipaměti:

Proces tvorby mezipaměti zahrnuje nejprve sekvenční zaplnění 32 MB paměti a poté provedení dvou průchodů algoritmu RandMemoHash od Sergia Demiana Lernera z Strict Memory Hard Hashing Functions (2014) (opens in a new tab). Výstupem je sada 524 288 64bajtových hodnot.

Funkce agregace dat

V některých případech používáme algoritmus inspirovaný FNV hashem (opens in a new tab) jako neasociativní náhradu za XOR. Všimněte si, že prvočíslo násobíme celým 32bitovým vstupem, na rozdíl od specifikace FNV-1, která násobí prvočíslo postupně jedním bajtem (oktetem).

FNV_PRIME = 0x01000193

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

Vezměte prosím na vědomí, že i když yellow paper specifikuje fnv jako v1*(FNV_PRIME ^ v2), všechny současné implementace konzistentně používají výše uvedenou definici.

Výpočet celé datové sady

Každá 64bajtová položka v celé 1 GB datové sadě se vypočítá následovně:

V podstatě kombinujeme data z 256 pseudonáhodně vybraných uzlů mezipaměti a hashujeme je, abychom vypočítali uzel datové sady. Celá datová sada je pak generována pomocí:

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

Hlavní smyčka

Nyní specifikujeme hlavní smyčku podobnou „hashimoto“, kde agregujeme data z celé datové sady, abychom vytvořili naši konečnou hodnotu pro konkrétní hlavičku a nonce. V níže uvedeném kódu představuje header SHA3-256 hash RLP reprezentace zkrácené hlavičky bloku, tedy hlavičky bez polí mixHash a nonce. nonce je osm bajtů 64bitového celého čísla bez znaménka v pořadí big-endian. Takže nonce[::-1] je osmi-bajtová little-endian reprezentace této hodnoty:

V podstatě udržujeme „mix“ o šířce 128 bajtů a opakovaně sekvenčně načítáme 128 bajtů z celé datové sady a používáme funkci fnv k jejich kombinaci s mixem. Používá se 128 bajtů sekvenčního přístupu, aby každé kolo algoritmu vždy načetlo celou stránku z RAM, čímž se minimalizují výpadky v translation lookaside bufferu (TLB), kterým by se ASIC teoreticky dokázaly vyhnout.

Pokud je výstup tohoto algoritmu pod požadovaným cílem, pak je nonce platná. Všimněte si, že dodatečná aplikace sha3_256 na konci zajišťuje, že existuje zprostředkující nonce, kterou lze poskytnout jako důkaz, že bylo vykonáno alespoň malé množství práce; toto rychlé vnější ověření PoW lze použít pro účely ochrany proti DDoS. Slouží také k poskytnutí statistické jistoty, že výsledek je nezkreslené 256bitové číslo.

Těžba

Algoritmus těžby je definován následovně:

def mine(full_size, dataset, header, difficulty):
    # doplnit cíl nulami pro porovnání s hashem na stejné číslici
    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

Definování seed hashe

Pro výpočet seed hashe, který by se použil k těžbě na vrcholu daného bloku, používáme následující algoritmus:

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

Všimněte si, že pro plynulou těžbu a ověřování doporučujeme předem vypočítat budoucí seed hashe a datové sady v samostatném vlákně.

Další čtení

Víte o komunitním zdroji, který vám pomohl? Upravte tuto stránku a přidejte ho!

Příloha

Následující kód by měl být přidán na začátek, pokud máte zájem spustit výše uvedenou specifikaci v Pythonu jako kód.

Velikosti dat

Následující vyhledávací tabulky poskytují přibližně 2048 tabelovaných epoch velikostí dat a velikostí mezipaměti.