Nadie fija el ritmo de bloques de Bitcoin. No hay planificador ni ninguna señal que le informe a la red cuánto hardware está enchufado. Lo que hay es un número en cada cabecera de bloque, una regla para recalcularlo cada 2.016 bloques y las marcas de tiempo que los propios mineros escribieron. Este es ese mecanismo en los términos que usa el código, citando Bitcoin Core v31.1 en todo el texto. Para quien no se haya cruzado con proof of work, qué hacen los mineros es la versión sin el detalle de bytes.
Qué está buscando realmente un minero
Una cabecera de bloque son 80 bytes: versión, el hash de la
cabecera anterior, la raíz merkle de las transacciones, una marca de tiempo, un campo de
cuatro bytes llamado nBits y un nonce de 32 bits. Minar es hashear esa cabecera dos veces
con SHA-256, leer el resultado como un número de 256 bits y preguntar si es igual o menor
que el objetivo codificado en nBits. Si no lo es, el minero cambia algo (el nonce, el
extra nonce de la coinbase, la marca de tiempo, el conjunto de transacciones) y vuelve a
hashear. No hay crédito parcial ni forma de dirigir la búsqueda, que es por qué la cantidad
de intentos es una magnitud medible y comprable.
La verificación en sí son cuatro líneas: CheckProofOfWorkImpl en
src/pow.cpp deriva
el objetivo a partir de nBits, compara y devuelve. nBits es una codificación compacta
de un byte de exponente y tres de mantisa, así que el objetivo lleva apenas 24 bits de
precisión. Un dial grueso, y el consenso no comprueba nada más sobre el trabajo.
La dificultad es un número de conveniencia
"Dificultad" no aparece en ninguna parte de esa verificación. Es una razón calculada para
consumo humano, y
GetDifficulty
vive en la capa RPC y no en el código de consenso. Divide el objetivo de dificultad 1, que
es lo que la forma compacta 0x1d00ffff decodifica de vuelta, por el objetivo actual.
Ese valor se parece pero no es igual al powLimit de mainnet, declarado en
chainparams.cpp
como 0x00000000ffffffff...ffff, porque la codificación compacta trunca la mantisa. Una
dificultad de 127,48 billones, donde estaba la red el 20 de agosto de 2026 según
mempool.space, significa que el objetivo en uso era esa
cantidad de veces más chico que el techo. Ningún nodo guarda la dificultad como estado de
consenso, y toda regla que sigue está escrita contra el objetivo.
El reajuste: cada 2.016 bloques, y como mucho por un factor de cuatro
Dos constantes fijan el ritmo, ambas en chainparams.cpp
(líneas 96 a 98):
consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // 1.209.600 segundos
consensus.nPowTargetSpacing = 10 * 60; // 600 segundos
El intervalo de reajuste no es una tercera constante.
DifficultyAdjustmentInterval()
es la primera dividida por la segunda: 2.016. Entre reajustes no se mueve nada:
GetNextWorkRequired devuelve sin cambios el nBits del bloque anterior salvo que la
altura en construcción sea múltiplo de 2.016, así que todos los bloques de un período se
minan contra un objetivo idéntico.
En el límite de un período, el nodo mide cuánto tardó realmente el anterior y escala:
nuevo_objetivo = objetivo_anterior * nActualTimespan / nPowTargetTimespan
Más lento de lo esperado significa un nActualTimespan mayor, un objetivo mayor y bloques
más fáciles. Más rápido significa lo contrario. Antes de esa multiplicación, el lapso
medido se acota
(src/pow.cpp):
if (nActualTimespan < params.nPowTargetTimespan/4)
nActualTimespan = params.nPowTargetTimespan/4;
if (nActualTimespan > params.nPowTargetTimespan*4)
nActualTimespan = params.nPowTargetTimespan*4;
Un reajuste puede mover el objetivo por un factor de cuatro y no más, en cualquiera de las dos direcciones. Esto se omite de forma rutinaria, y decide cómo se resuelve un shock. Supongamos que nueve décimas partes del hashrate desaparecen de un día para el otro. Los bloques tardarían diez veces más, así que el período correría unos 140 días en vez de 14. El tope limita la corrección a cuatro, lo que deja el intervalo en unos 25 minutos, todavía dos veces y media el objetivo. Recién el período siguiente, otros 35 días más o menos, termina el trabajo. La cota protege a la cadena de un lapso medido disparatado o manipulado, y lo paga haciendo que un colapso genuino necesite dos reajustes para absorberse.
El error de uno que no se puede corregir
Encontrar el inicio del período se ve así (src/pow.cpp):
// Go back by what we want to be 14 days worth of blocks
int nHeightFirst = pindexLast->nHeight - (params.DifficultyAdjustmentInterval()-1);
pindexLast es el último bloque del período que termina. Retroceder 2.015 bloques cae en
el primer bloque de ese mismo período, lo cual es correcto como índice y equivocado como
duración: el espacio entre dos bloques separados por 2.015 contiene 2.015 intervalos, no
2.016. Esa cifra se divide después por 1.209.600 segundos, lo que se suponía que iban a
tardar 2.016 intervalos.
Hagamos el punto fijo. Con hashrate estable y marcas de tiempo honestas, el reajuste deja
de moverse cuando nActualTimespan es igual a 1.209.600, y ese lapso cubre 2.015
intervalos. Entonces el intervalo al que converge el código es 1.209.600 / 2.015, o sea
600,2978 segundos: diez minutos y unas tres décimas de segundo. El sesgo corre hacia lo
lento, no hacia lo rápido, en torno al 0,05 por ciento, y cada período de dos semanas se
pasa unos diez minutos, que es exactamente el intervalo que quedó afuera. Ninguna fuente
publica esta cifra, así que conviene revisar la aritmética en lugar de creerla.
Ese es un estado estacionario idealizado, no una medición. El intervalo promedio desde el bloque génesis hasta la altura 963.283 el 20 de agosto de 2026 da 577 segundos, nueve minutos y 37 segundos. Eso no dice nada sobre el error de uno. Dice que el hashrate creció durante diecisiete años, así que los bloques dentro de cada período siguen llegando más rápido que el objetivo fijado al comienzo, y un sesgo del 0,05 por ciento en la dirección contraria desaparece debajo.
La deriva es la mitad inofensiva. Lo que importa es que las ventanas de medición no se solapan. Una ventana va del primer bloque de un período al último, y la siguiente arranca en el bloque posterior a ese, así que el intervalo entre dos períodos no lo mide nadie. Una marca de tiempo equivocada o deshonesta en el bloque que cierra una ventana nunca queda descontada por la siguiente. Ese hueco es la puerta por la que entra el ataque time warp.
Corregir el error de uno exigiría un hard fork, y la razón es una línea de validation.cpp:
if (block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams))
return state.Invalid(..., "bad-diffbits", "incorrect proof of work");
El nBits de una cabecera tiene que ser exactamente igual a lo que calcula el nodo que
valida. No hay "más o menos", ni una dirección que sea más permisiva, así que cambiar la
fórmula en cualquier sentido implica que los nodos actualizados y los no actualizados
rechazan los bloques de los otros. Una división de cadena, por un 0,05 por ciento. Nadie
propuso pagar eso.
Las marcas de tiempo no son un reloj
Todo el ajuste corre sobre números que los mineros escriben en sus propias cabeceras. Dos
reglas de consenso en
ContextualCheckBlockHeader
los limitan, y ninguna es tan estricta como suele suponerse.
Una marca de tiempo tiene que ser estrictamente mayor que el median time past, la mediana de las once marcas de tiempo anteriores (chain.h). Como es una mediana de once y no una comparación contra el bloque padre, la marca de tiempo de un bloque puede ser legítimamente anterior a la de su padre. Las marcas de tiempo de los bloques no son monótonas, y el código que supone que lo son está equivocado.
Una marca de tiempo tampoco puede estar más de MAX_FUTURE_BLOCK_TIME, definido como
2 * 60 * 60 (chain.h),
por delante del reloj propio del nodo que valida, no de uno de consenso: Bitcoin Core 27.0
quitó el tiempo ajustado por la red del código de consenso,
así que quien opere un nodo cuyo reloj se desvíe lo suficiente se sale del consenso por su
cuenta. Con espaciado normal, el median time past queda unos cinco bloques atrás, más o
menos cincuenta minutos por detrás de la punta, así que la franja legal para una marca de
tiempo nueva ronda las tres horas de ancho.
El reajuste lee las marcas de tiempo crudas de las cabeceras, no el median time past. Así
que el minero del último bloque de un período, y el del primero, tienen cada uno un par de
horas de margen sobre una magnitud que nominalmente vale 1.209.600 segundos. Dos horas
sobre 336 es alrededor del 0,6 por ciento en cada extremo: real, acotado y de poco valor
una sola vez. Hacerlo período tras período es el ataque time warp, que necesita hashrate
mayoritario sostenido y a la vista de todos. La contramedida existe: una regla que limita
cuánto puede quedar la marca de tiempo de un bloque de reajuste por detrás de la de su
predecesor, en 600 segundos en testnet4 bajo
BIP 94 y en 7.200
segundos en la propuesta para mainnet,
BIP 54. Ninguna aplica acá. BIP
54 no tiene parámetros de activación, y
chainparams.cpp
deja enforce_BIP94 = false para mainnet. Y BIP 54 tampoco cerraría el error de uno: su
segunda regla está escrita ella misma en términos del bloque 2.015 hacia atrás.
Cuando el hashrate se va, la red espera
Cuando China ordenó a sus mineros que pararan en 2021 y cerca de la mitad del hashrate de la red se apagó, los bloques se hicieron más lentos y siguieron lentos durante semanas. El 3 de julio de 2021 la dificultad cayó 27,94 por ciento, el mayor movimiento a la baja registrado, y el intervalo volvió.
No había un camino más rápido. El objetivo es constante durante 2.016 bloques por construcción, la única entrada son las marcas de tiempo transcurridas, y el único momento en que se leen es el límite del período. Reaccionar antes implicaría muestrear ventanas más cortas, y las ventanas cortas son más baratas de mover con exactamente el margen descrito arriba. Bitcoin compra robustez negándose a ser reactivo, y el precio lo pagan en tiempos de confirmación quienes están transaccionando durante el hueco. Es incómodo, y es el sistema funcionando.
Lo que no hace
- No apunta a un precio. Ningún precio entra en el cálculo. La causalidad va al revés: el precio mueve el hashrate, el hashrate mueve el próximo reajuste.
- No responde a la demanda de espacio en bloque. Un mempool lleno cambia las comisiones, no la dificultad.
- No se ajusta de forma continua. Un escalón cada 2.016 bloques, y después plano.
- No lleva un calendario. Los halvings se disparan por altura de bloque, así que una cadena lenta llega a ellos más tarde en tiempo de reloj y acuña exactamente la misma cantidad de monedas.
- No garantiza diez minutos. Apunta a la media de un proceso sin memoria. Incluso en equilibrio perfecto los intervalos se distribuyen de forma exponencial: alrededor del 63 por ciento de los bloques llegan dentro de los diez minutos del anterior, y cerca de uno de cada 400 tarda más de una hora. Un bloque lento aislado no es evidencia de nada.
Todo el aparato son dos marcas de tiempo, una división y un tope, evaluados de forma idéntica por cada nodo. Todo lo que Bitcoin hace ante un shock de hashrate, lo hace en ese límite, y en ningún otro lado.
