メインコンテンツへスキップ
Change page

Ethash

ページの最終更新: 2026年4月15日

Ethashは、イーサリアムのプルーフ・オブ・ワークのマイニングアルゴリズムでした。 プルーフ・オブ・ワークは、現在『完全に停止』となっています。イーサリアムは今、代わりにプルーフ・オブ・ステークによって安全が確保されています。 マージプルーフ・オブ・ステークステーキングについて詳しく読む。 このページについては、これまでのイーサリアムの歩みを学ぶための参考としてお読みください。

EthashはDagger-Hashimotoアルゴリズムの修正版です。 Ethashのプルーフ・オブ・ワークはメモリハード (opens in a new tab)であり、このアルゴリズムはASIC耐性があると考えられていました。 最終的には、Ethash ASICが開発されましたが、GPUマイニングは、プルーフ・オブ・ワークが停止されるまでが実行可能なオプションでした。 Ethashは現在でも、イーサリアム以外のプルール・オブ・ワーク・ネットワークで他のコインのマイニングに使われています。

Ethashの仕組み

ノンス (nonce)とブロックヘッダーに依存する固定リソースのサブセットを選択する必要があるプルーフ・オブ・ワーク・アルゴリズムで、メモリハードを実現します。 この(数ギガバイトの大きさの)リソースは、DAGと呼ばれます。 DAGは、30000ブロックごと、エポックと呼ばれる最大125時間(約5.2日)のウィンドウで、変更されます。また生成にはしばらく時間がかかります。 DAGはブロックの高さのみに依存するため、事前に生成はできますが、そうでない場合、クライアントはブロックの生成プロセスが終わるまで待つ必要があります。 クライアントが事前にDAGを生成してキャッシュしないと、各エポックの遷移で大規模なブロック遅延がネットワークに発生する可能性があります。 プルーフ・オブ・ワークを検証するために、DAGが生成される必要がないことに留意してください。基本的に低CPUと小さなメモリ両方で検証できます。

アルゴリズムが取る一般的なルートは以下のとおりです。

  1. 各ブロックについて、その時点までのブロックヘッダーをスキャンすることで計算できるシードが存在します。
  2. シードから、16MBの疑似ランダムキャッシュを計算できます。 ライトクライアントは、キャッシュを保存する。
  3. キャッシュから、データセット内の各アイテムがキャッシュ内の少数のアイテムのみに依存するという特性を持つ、1GBのデータセットを生成できます。 フルクライアントとマイナーは、データセットを保存する。 データセットは時間とともに線形的に増加する。
  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」ハッシュが参照されることを覚えておいてください。

パラメータ

Ethashのキャッシュとデータセットのパラメータは、ブロック番号に依存します。 キャッシュサイズとデータセットサイズは、両方とも線形に増えていきます。しかし、周期的な動作につながる偶発的な規則性が発生するリスクを減らすために、線形的に増加するしきい値を下回る最大の素数を常に取ります。

データセットとキャッシュサイズの値の表は、付録に記載されています。

キャッシュ生成

以下に、キャッシュを生成する関数を記述します。

キャッシュ生成プロセスでは、まず32MBのメモリを順番に埋め、次にSergio Demian LernerのStrict Memory Hard Hashing Functions (2014) (opens in a new tab)にある_RandMemoHash_アルゴリズムの2パスを実行します。 出力は、524288個の64バイトの値のセットです。

データ集約関数

FNVハッシュ (opens in a new tab)に触発されたアルゴリズムを、XORの非結合的な代替として使用する場合があります。 素数を1バイト(オクテット)ずつ順番に乗算するFNV-1の仕様ではなく、素数を全32ビットの入力で乗算することに注意してください。

FNV_PRIME = 0x01000193

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

イエローペーパーでは、FNVをv1*(FNV_PRIME ^ v2)と指定していますが、現在の実装ではすべて上記の定義で統一しています。

フルデータセットの計算

1GBのフルデータセットの64バイトの各アイテムは、次のように計算されます。

基本的に、疑似乱数で選ばれた256個のキャッシュノードからデータを結合し、データセットノードを計算するためにハッシュ化します。 そのあと、データセット全体が、次のように生成されます。

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

メインループ

ここでは、メインのハシモトに似たループを記述します。特定のヘッダーとノンス (nonce)の最終的な値を生成するために、フルデータセットからデータを集約します。 以下のコードでは、headerは、_切り捨てられた_ブロックヘッダー、つまりmixHashnonceフィールドを除いたヘッダーのRLP表現のSHA3-256_ハッシュ_を表します。 nonceは、ビッグエンディアンオーダーの64ビット符号なし整数の8バイトです。 したがって、nonce[::-1]は、その値の8バイトのリトルエンディアン表現です:

基本的に、幅128バイトの"mix"を維持し、フルデータセットから128バイトを繰り返しシーケンシャルにフェッチし、fnv関数を使用してそれをmixと結合します。 128バイトのシーケンシャルアクセス が使用されており、アルゴリズムの各ラウンドは、常にRAMから完全なページをフェッチし、理論的にASICが回避できるトランスレーション・ルックアサイド・バッファのミスを最小限にします。

アルゴリズムの出力が目標値を下回っている場合は、ノンス (nonce)は有効です。 最後に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

スムーズなマイニングと検証のために、別々のスレッドで将来のシードハッシュとデータセットを事前計算することを推奨します。

参考リンク

役に立つコミュニティリソースを知っていますか? Edit this page and add it!

付録

上記のpythonで記述された仕様をコードとして実行する場合は、以下のコードを先頭に付け足してください。

データサイズ

次のルックアップテーブルは、データサイズとキャッシュサイズの約2048個のエポックの一覧です。

この記事は役に立ちましたか?