Schwierigkeitsalgorithmus & Fork-Choice-Regeln

Ein präziser Rundgang durch die Historie der Schwierigkeitsanpassung von Parallax — BTC-artige DAA ab Genesis, das ASERT-Upgrade bei Block 17.560 (PIP-0002) und die Nakamoto-Fork-Choice-Regel auf Basis kumulierter Arbeit.

Konsensparameter
ParameterSymbolWertAnmerkungen
Ziel-Blockintervall
τ
600 s
Bitcoin-artiges Ziel
Grenze der zukünftigen Zeitabweichung
300 s
5 Minuten
MTP-Stichprobengröße
11 Blöcke
Median der letzten 11 Zeitstempel
Historie des Schwierigkeitsalgorithmus
BTC-artige DAA → ASERT
BTC-artige 2016-Block-Fenster von Genesis bis 17.559; ASERT (aserti3-2d) ab Block 17.560 (PIP-0002).
Überblick
Parallax strebt 10-Minuten-Blöcke mittels XHash-Proof-of-Work und eines Per-Block-ASERT-Schwierigkeitsalgorithmus an — nach einer anfänglichen BTC-artigen DAA-Phase.
  • Von Genesis bis Block 17.559 verwendete Parallax ein Bitcoin-artiges 2016-Block-Anpassungsfenster (BTC-artige DAA).
  • PIP-0002 (Migration vom BTC-artigen Schwierigkeitsalgorithmus zu ASERT) aktivierte ASERT bei Block 17.560.
  • ASERT (aserti3-2d, wie von Bitcoin Cash genutzt) passt die Schwierigkeit pro Block relativ zu einem festen Anker an und konvergiert bei Hashrate-Schocks sanft gegen das 600-s-Ziel.
  • Median-Time-Past (MTP, Median der letzten 11) sichert die Zeitstempel-Gültigkeit; Nodes lehnen Header ab, die mehr als +300 s in der Zukunft liegen, und prüfen den PoW mit target = ⌊(2^256−1)/D⌋.
Target ↔ Schwierigkeit
Die von der XHash-Verifikation verwendete Arbeitsschwellen-Abbildung (für BTC-DAA- und ASERT-Ära gleichermaßen gültig).
  • Sei TWO256M1 = 2^256 − 1. Der Header ist gültig, wenn XHash(header) ≤ target, wobei target = ⌊TWO256M1 / D⌋.
  • Höhere Schwierigkeit D ⇒ kleineres Target ⇒ schwierigerer Block.
  • Header.MixDigest muss dem aus Hashimoto berechneten Digest entsprechen (Light-/Full-Pfad).
  • Die Schwierigkeit muss strikt positiv sein; null oder negativ ist ungültig.
Target-Berechnung (konzeptionell)
Pseudocode
// Given difficulty D (big integer)
TWO256M1 = (1n << 256n) - 1n
target   = TWO256M1 / D
valid    = BigIntFromBytes(result) <= target
Schwierigkeitsanpassung: BTC-artige DAA → ASERT
Historische 2016-Block-Fenster, moderne Per-Block-ASERT-Anpassung relativ zu einem Anker.
  • Genesis → Block 17.559: CalcNakamotoDifficulty() implementiert ein Bitcoin-artiges 2016-Block-Fenster mit Epochenankern.
  • Ab Block 17.560: CalcAsertDifficulty() implementiert aserti3-2d mit einem festen Anker {anchorHeight, anchorParentTime, anchorTarget}.
  • ASERT verwendet den Höhenversatz Δh und die verstrichene Zeit Δt relativ zum Anker, um die Schwierigkeit mit einer Halbwertszeit von 2 Tagen in Richtung des 600-s-Ziels zu steuern.
  • Historische Blöcke behalten ihre ursprüngliche Schwierigkeit aus der BTC-artigen DAA und werden weiterhin nach diesen Regeln validiert; die vorausblickende Anpassung erfolgt vollständig über ASERT.
Höhenabhängige Schwierigkeitswahl (konzeptionell)
Pseudocode
// Difficulty selection by era
CalcDifficulty(config, anchor, parent, header):
  if height(header) < 17560:
    // BTC-style DAA: 2016-block window with epoch anchors
    return CalcNakamotoDifficulty(config, parent)
  else:
    // ASERT: per-block retarget relative to fixed anchor
    return CalcAsertDifficulty(config, anchor, parent, header)

// ASERT core idea (fixed-point, aserti3-2d)
CalcAsertDifficulty(config, anchor, parent, header):
  Δh = height(header) - anchor.height
  Δt = header.Time - anchor.parentTime   // seconds
  // τ = 600 s target, T_half = 172800 s (2 days)
  e  = ((Δt - Δh * τ) * RADIX) / T_half  // fixed-point exponent
  target = anchor.target * 2^e           // via cubic approximation in integer math
  target = clamp(target, 1, maxTarget)
  return DifficultyFromTarget(target)
Median-Time-Past (MTP)
Zeitstempelkonsistenz für Gültigkeit und Zeit-Warp-Widerstand.
  • MTP(parent) = Median der letzten 11 Blockzeitstempel, endend beim Parent.
  • Gültigkeit erfordert header.Time > MTP(parent) (strikte Ungleichung).
  • Grenze der zukünftigen Zeitabweichung: header.Time ≤ jetzt + 300 s.
  • Unter ASERT wird die verstrichene Zeit relativ zum Anker von Zeitstempeln bestimmt, die durch MTP beschränkt sind — das verhindert klassische Long-Range-Zeit-Warp-Angriffe gegen den Schwierigkeitsalgorithmus.
MTP-Berechnung
Pseudocode
MTP(n):
  ts = timestamps(n, upTo=11) // back from n inclusive
  sort(ts)
  return ts[len(ts)//2]
Fork-Choice-Regel
Die schwerste gültige Kette nach kumulierter Arbeit — unabhängig von der aktiven Schwierigkeits-Ära.
  • ChainWork[tip] = ChainWork[parent] + Work(block) pflegen.
  • Work(block) ist eine monotone Funktion von Target/Schwierigkeit; jede konsistente Definition liefert eine äquivalente Ordnung.
  • Die gültige Spitze mit der größten ChainWork wird ausgewählt; Gleichstände lassen sich lexikographisch über den Tip-Hash auflösen.
  • Ungültige Header (Zeit, PoW, BTC-DAA-/ASERT-Regeln) werden vor der Fork-Auswahl ausgeschlossen.
Kumulierte Arbeit (konzeptionell)
Pseudocode
Work(block):
  target = TWO256M1 / Difficulty(block)
  // Use an approximation that preserves ordering; e.g.,
  return TWO256M1 / (target + 1)

SelectBest(tips):
  return argmax(tips, ChainWork[tip])
Reorgs & probabilistische Finalität
Tiefenbasierte Garantien statt absoluter Finalität.
  • Die Bestätigungstiefe k senkt die Reorg-Wahrscheinlichkeit exponentiell mit k.
  • Wallets/UIs wählen k nach dem Wert im Risiko (z. B. standardmäßig 6 Bestätigungen bei hohen Beträgen).
  • Nodes können praktische Schutzmechanismen implementieren (z. B. maximale Reorg-Tiefe), um DoS durch pathologische Peers zu vermeiden.
  • ASERTs glattere, per-Block erfolgende Schwierigkeitsanpassung reduziert Anreize für oszillationsgetriebene oder opportunistische lange Reorgs im Vergleich zur BTC-artigen DAA mit großen Fenstern.
Reorg-Handhabung (konzeptionell)
Pseudocode
OnNewTip(candidate):
  if ChainWork[candidate] > ChainWork[currentTip]:
    currentTip = candidate
    ReorgTo(candidate)
Angriffe & Gegenmaßnahmen
Wichtige Vektoren im Zusammenhang mit dem Schwierigkeitsdesign von Parallax.
  • Zeit-Warp: Strikte MTP-Durchsetzung plus ASERTs Per-Block-Feedback (keine langen statischen Fenster) entschärfen die klassische BTC-artige 2016-Block-Zeit-Warp-Manipulation.
  • Abweichung zukünftiger Zeitstempel: Header, die mehr als +300 s vor der lokalen Zeit liegen, werden abgelehnt.
  • MixDigest-Spoofing: header.MixDigest muss der Hashimoto-Ausgabe entsprechen (Light/Full).
Teilmenge der Header-Gültigkeit
Pseudocode
ValidHeader(h, parent):
  require(len(h.Extra) <= MaximumExtraDataSize)
  require(h.Time <= now() + 300)
  require(h.Time > MTP(parent))
  require(h.Difficulty > 0)
  // difficulty rules depend on height:
  //   < 17560: BTC-style DAA epoch invariants
  //   ≥ 17560: ASERT anchor-based invariants
  // PoW: MixDigest match & XHash(h) <= targetFrom(D)
Pipeline

Ende-zu-Ende-Auswahlablauf

Header werden auf Extra-Größe, Zeit (MTP und zukünftige Abweichung), epochenspezifische Schwierigkeitsregeln (BTC-artige DAA für frühe Blöcke, ASERT ab Höhe 17.560), Gas-Limits/EIPs, Höheninkrement und PoW-Seal geprüft. Gültige Blöcke erweitern ChainWork, und die schwerste Spitze ist kanonisch.

1
Validieren
2
Anker / Ära prüfen
3
Schwierigkeit berechnen (DAA/ASERT)
4
Arbeit akkumulieren
5
Schwerste auswählen