XHash

Parallaxが採用するメモリハードなProof of Work。Ethash系のHashimotoに、ParallaxのASERTベース難易度、コンセンサスルール、エポック処理を組み合わせたもの。

コンセンサス関連の詳細
xhash/consensus.goとParallaxのチェーン設定に基づきます。
項目値 / 挙動備考
ハッシュ関数 (シール)
Legacy Keccak-256
特定のヘッダフィールドに対するRLP
ターゲットマッピング
target = ⌊(2^256−1)/D⌋
結果は ≤ target でなければならない
MixDigest
計算されたdigestと等しくなければならない
不一致 ⇒ PoW無効
MTP
直近11個の中央値
Time > MTP(parent) を強制、未来ドリフトは ≤ 300秒
エポック長
設定で定義 (例: 720ブロック)
キャッシュ/DAG再生成の頻度を決定
難易度アルゴリズム
ASERT (ブロック単位、アンカーベース)
aserti3-2d。コンセンサスがDを計算し、XHashがPoWを通じてそれを強制
概要
XHashはParallaxのProof of Workエンジンです。Ethash系のHashimoto (light/full) に、Parallax固有のコンセンサス結線、ASERTベースの難易度マッピング、エポック処理を備えています。
  • マイニングは、ヘッダのシールハッシュと64ビットnonceに対してHashimotoを評価し、キャッシュ (light) かデータセット (full) を使用します。
  • 検証ではMixDigestの一致を確認し、結果を難易度から導かれるターゲット target = ⌊(2^256−1)/D⌋ と比較します。
  • シールハッシュは、特定のヘッダフィールドのRLPリストに対してLegacy Keccak-256を適用したものです。
SealHash
疑似コード
SealHash(header):
  enc = [
    header.ParentHash,
    header.Coinbase,
    header.Root,
    header.TxHash,
    header.ReceiptHash,
    header.Bloom,
    header.Difficulty,
    header.Number,
    header.GasLimit,
    header.GasUsed,
    header.Time,
    header.Extra,
    header.EpochStartTime,
  ]
  if header.BaseFee != nil:
    enc.append(header.BaseFee)
  return keccak256(rlp.encode(enc))
マイニングループ
Hashimoto-light/full と64ビットnonce探索、内側ループではリトルエンディアンでのターゲット比較。
  • マイナーは nonce ∈ [0..2^64−1] を走査し、(digest, result) = hashimoto(cache/dataset, sealHash, nonce) を計算します。
  • MixDigestはヘッダフィールドと厳密に一致し、resultは ≤ target でなければなりません。
  • フルマイナーはエポックごとのデータセットを使用し、ライト検証者/ノードはキャッシュで検証できます (完全なDAG不要)。
  • データセット/キャッシュはエポック境界 (例: 720ブロックごと) で再生成されます。
nonce探索 (疑似コード)
疑似コード
mine(header, cacheOrDataset):
  target = floor((2^256 - 1) / header.Difficulty)
  nonce  = random64()
  loop:
    (mix, res) = hashimoto(cacheOrDataset, SealHash(header), nonce)
    if mix == header.MixDigest and Big(res) <= target:
      return nonce
    nonce = (nonce + 1) mod 2^64
ヘッダ検証
ノードがPoWヘッダを受け入れる前にチェックする項目。
  • Extraのサイズは MaximumExtraDataSize 以下。
  • Time ≤ now + 300秒、かつ Time > MTP(parent) (直近11個の中央値)。
  • 難易度は、所与のparentおよびヘッダに対してコンセンサスの難易度エンジン (ASERT) と一致しなければなりません。
  • PoWシール: MixDigestの一致と XHash(header) ≤ target(two256m1 / D)。
verifySeal (概念)
疑似コード
verifySeal(h):
  require(h.Difficulty > 0)
  if fulldag:
    (mix, res) = hashimotoFull(dataset(epoch(h.Number)), SealHash(h), h.Nonce)
  else:
    (mix, res) = hashimotoLight(datasetSize(h.Number), cache(epoch(h.Number)), SealHash(h), h.Nonce)
  require(mix == h.MixDigest)
  target = floor((2^256 - 1) / h.Difficulty)
  require(Big(res) <= target)
エポック、キャッシュとデータセット (DAG)
再生成の頻度と、マイナー互換性に関する注意点。
  • エポック番号はブロック高から導出され、キャッシュ/データセットのサイズはエポックを通じて datasetSize(height) で決まります。
  • Parallaxはレガシー Ethash より短いエポック (例: 720ブロック) を採用し、10分ブロックで約5日の再生成周期に合わせています。
  • ノードはキャッシュを保持することで検証を軽量化でき、ヘッダの検証に完全なDAGは不要です。
再生成トリガー
疑似コード
if newEpoch(height):
  regenerate cache
  if mining full: regenerate dataset
難易度とアンカー
PoWとASERT難易度スケジュールの相互作用。
  • 難易度はASERTスケジューラによって計算され、XHashは選ばれた難易度をターゲットチェックによって単純に強制します。
  • コンセンサスはASERTアンカー (高さ、parentTime、target) を保持し、ヘッダのメタデータ (例: EpochStartTimeや専用フィールド) を用いてアンカーのコンテキストを再構築します。
  • CalcAsertDifficulty(config, anchor, parent, header) が、ヘッダに対する期待される難易度を導きます。
  • 難易度とアンカーの不変条件は、フォーク選択の前にヘッダ検証で強制されます。
難易度の不変条件 (概念)
疑似コード
verifyDifficulty(h, parent, anchor):
  expected = CalcAsertDifficulty(config, anchor, parent, h)
  require(h.Difficulty == expected)