Algoritmo de Dificultad y Reglas de Elección de Fork

Un recorrido preciso por el historial de ajuste de dificultad de Parallax: DAA estilo BTC desde el génesis, la actualización a ASERT en el bloque 17.560 (PIP-0002) y la regla de elección de fork Nakamoto basada en trabajo acumulado.

Parámetros de Consenso
ParámetroSímboloValorNotas
Intervalo de bloque objetivo
τ
600 s
Objetivo al estilo Bitcoin
Tolerancia futura de deriva temporal
300 s
5 minutos
Tamaño de muestra MTP
11 bloques
Mediana de los últimos 11 timestamps
Historial del algoritmo de dificultad
DAA estilo BTC → ASERT
Ventanas de 2016 bloques estilo BTC desde el génesis al 17.559; ASERT (aserti3-2d) para bloques ≥ 17.560 (PIP-0002).
Visión General
Parallax apunta a bloques de 10 minutos usando Proof of Work XHash y un algoritmo de dificultad ASERT por bloque, tras una fase inicial con DAA estilo BTC.
  • Desde el génesis hasta el bloque 17.559, Parallax usó una ventana de ajuste de dificultad de 2016 bloques al estilo Bitcoin (DAA estilo BTC).
  • El PIP-0002 (Migración del Algoritmo de Ajuste de Dificultad estilo BTC a ASERT) activó ASERT en el bloque 17.560.
  • ASERT (aserti3-2d, como el usado por Bitcoin Cash) ajusta la dificultad en cada bloque respecto a un anclaje fijo, convergiendo suavemente hacia el objetivo de 600 s bajo shocks de hashrate.
  • El Median-Time-Past (MTP, mediana de los últimos 11) protege la validez del timestamp; los nodos rechazan cabeceras con más de +300s de adelanto y verifican el PoW con target = ⌊(2^256−1)/D⌋.
Objetivo ↔ Dificultad
Mapeo del umbral de trabajo usado por la verificación XHash (común a las eras DAA BTC y ASERT).
  • Sea TWO256M1 = 2^256 − 1. La cabecera es válida si XHash(header) ≤ target, donde target = ⌊TWO256M1 / D⌋.
  • Mayor dificultad D ⇒ target más pequeño ⇒ bloque más difícil.
  • Header.MixDigest debe coincidir con el digest calculado por hashimoto (vías light/full).
  • La dificultad debe ser estrictamente positiva; cero o negativa es inválida.
Cálculo del objetivo (conceptual)
pseudocódigo
// Given difficulty D (big integer)
TWO256M1 = (1n << 256n) - 1n
target   = TWO256M1 / D
valid    = BigIntFromBytes(result) <= target
Ajuste de Dificultad: DAA estilo BTC → ASERT
Ventanas históricas de 2016 bloques, ASERT moderno por bloque respecto a un anclaje.
  • Génesis → bloque 17.559: CalcNakamotoDifficulty() implementa una ventana de 2016 bloques al estilo Bitcoin usando anclajes de época.
  • Bloque 17.560 en adelante: CalcAsertDifficulty() implementa aserti3-2d usando un anclaje fijo {anchorHeight, anchorParentTime, anchorTarget}.
  • ASERT usa el desfase de altura Δh y el tiempo transcurrido Δt respecto al anclaje para empujar la dificultad hacia el objetivo de 600 s con una vida media de 2 días.
  • Los bloques históricos conservan su dificultad original DAA estilo BTC y siguen validándose bajo esas reglas; el ajuste hacia adelante es enteramente basado en ASERT.
Selección de dificultad dependiente de la altura (conceptual)
pseudocódigo
// 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)
Cordura de timestamps para validez y resistencia a time-warp.
  • MTP(padre) = mediana de los últimos 11 timestamps de bloque terminando en el padre.
  • La validez exige header.Time > MTP(padre) (desigualdad estricta).
  • Tolerancia futura: header.Time ≤ ahora + 300s.
  • Bajo ASERT, el tiempo transcurrido respecto al anclaje se basa en timestamps restringidos por MTP, lo que previene los clásicos ataques de time-warp de largo alcance contra el algoritmo de dificultad.
Cómputo del MTP
pseudocódigo
MTP(n):
  ts = timestamps(n, upTo=11) // back from n inclusive
  sort(ts)
  return ts[len(ts)//2]
Regla de Elección de Fork
Cadena válida más pesada por trabajo acumulado, independiente de la era de dificultad activa.
  • Se mantiene ChainWork[tip] = ChainWork[parent] + Work(block).
  • Work(block) es una función monótona del target/dificultad; cualquier definición consistente produce un orden equivalente.
  • Se selecciona la punta válida con mayor ChainWork; los empates pueden resolverse lexicográficamente por el hash de la punta.
  • Las cabeceras inválidas (time, PoW, reglas DAA BTC/ASERT) se excluyen antes de la elección de fork.
Trabajo acumulado (conceptual)
pseudocódigo
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 y Finalidad Probabilística
Garantías basadas en profundidad en lugar de finalidad absoluta.
  • La profundidad de confirmación k reduce exponencialmente la probabilidad de reorg con k.
  • Las wallets/UIs eligen k según el valor en riesgo (p. ej., 6 confirmaciones por defecto para montos altos).
  • Los nodos pueden implementar salvaguardas prácticas (p. ej., profundidad máxima de reorg) para evitar DoS desde pares patológicos.
  • La respuesta de dificultad más suave y por bloque de ASERT reduce el incentivo a reorgs largos oportunistas u oscilatorios frente a las grandes ventanas del DAA estilo BTC.
Gestión de reorgs (conceptual)
pseudocódigo
OnNewTip(candidate):
  if ChainWork[candidate] > ChainWork[currentTip]:
    currentTip = candidate
    ReorgTo(candidate)
Ataques y Mitigaciones
Vectores clave relevantes para el diseño de dificultad de Parallax.
  • Time-warp: la aplicación estricta de MTP más la realimentación por bloque de ASERT (sin grandes ventanas estáticas) mitigan la clásica manipulación por time-warp de la ventana de 2016 bloques al estilo BTC.
  • Desviación futura del timestamp: se rechazan cabeceras con más de +300s por delante del tiempo local.
  • Falsificación del MixDigest: header.MixDigest debe coincidir con la salida de hashimoto (light/full).
Subconjunto de validez de cabecera
pseudocódigo
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

Flujo de selección de extremo a extremo

Las cabeceras se comprueban por tamaño de Extra, tiempo (MTP y deriva futura), reglas de dificultad específicas de la era (DAA estilo BTC para bloques tempranos, ASERT para altura ≥ 17.560), límites de gas/EIPs, incremento de altura y sello de PoW. Los bloques válidos amplían ChainWork, y la punta más pesada es la canónica.

1
Validar
2
Comprobar Anclaje / Era
3
Calcular Dificultad (DAA/ASERT)
4
Acumular Trabajo
5
Seleccionar Más Pesada