Substrate: del runtime al consenso propio
Artículo 12 de 20
60%
completado al llegar aquí
Sistemas distribuidosNota de investigación18 min de lectura
BABE: una lotería VRF para producir bloques
Cómo BABE sortea cada slot con una VRF secreta, por qué a veces ganan dos o nadie, y qué hacen las épocas, los slots secundarios y el fork choice.
Ruta Substrate: 0/20
Prerequisitos recomendados
Si alguno de estos conceptos todavía está medio nebuloso, empieza por aquí. Te ahorra tropiezos y un par de cejas fruncidas.
Un equipo integra una cadena basada en Substrate (Polkadot SDK) con su sistema contable. El primer día, el indexador registra dos bloques distintos con la misma altura, separados por unos milisegundos. Uno desaparece poco después. El equipo abre un incidente: "la cadena se bifurcó". Nadie atacó a nadie. La cadena usa BABE, y en BABE dos autoridades pueden ganar el mismo slot de forma completamente legítima.
En el capítulo anterior vimos Aura: turnos fijos, públicos y predecibles. BABE conserva la idea de slot pero cambia la pregunta "a quién le toca" por "quién ganó el sorteo", y el sorteo es secreto hasta que el ganador publica su bloque. Este capítulo explica la lotería, sus consecuencias (forks temporales y slots sin ganador) y las piezas que la hacen segura: épocas, aleatoriedad anunciada con antelación y una regla de cadena propia.
Brújula de lectura
Actor, evidencia y estado
Actor
Autoridad que ganó la lotería del slotCada autoridad evalúa en privado su VRF; nadie más sabe si ganó hasta que publica.
Evidencia
Salida y prueba de la VRFLa cabecera lleva la prueba; cualquiera la verifica con la clave pública y la aleatoriedad de la época.
Estado
Cadena con más bloques primariosPuede haber forks temporales; la finalidad la pone GRANDPA.
Por qué esconder al próximo autor
Aura tiene una debilidad evidente: cualquiera sabe quién producirá el bloque dentro de diez slots. Un atacante con capacidad de saturar la red de una sola máquina puede ir apagando, por turnos, a cada autor justo antes de su slot. BABE, cuyo nombre significa Blind Assignment for Blockchain Extension, ataca ese problema con una asignación ciega: cada autoridad sabe si ganó, pero los demás se enteran solo cuando aparece el bloque.
La herramienta es una VRF (verifiable random function, función aleatoria verificable). Con su clave secreta, una autoridad calcula sobre una entrada un número que parece aleatorio y una prueba. Con la clave pública, cualquiera comprueba que ese número salió de esa entrada y de esa clave, pero nadie puede calcularlo por adelantado sin la clave secreta. El código del SDK lo resume: "BABE is a slot-based block production mechanism which uses a VRF PRNG to randomly perform the slot allocation." [1]
BABE no partió de cero. La especificación del protocolo dice que está "designed based on [Ouroboros Praos]", el protocolo de prueba de participación publicado en 2017. [2] La investigación de Web3 Foundation señala las dos diferencias principales: la selección de la mejor cadena, que en BABE se apoya en GRANDPA y en la cadena más larga, y el supuesto de sincronización de slots, porque los productores no dependen de una autoridad central de hora como NTP. [3] El algoritmo de ajuste de reloj que describe ese documento es diseño de investigación; si el nodo actual lo implementa tal cual queda a validar.
La lotería de cada slot
En cada slot, cada autoridad evalúa la VRF sobre la aleatoriedad de la época y el número de slot. El código lo describe así: si el número "is lower than a given threshold (which is proportional to their weight/stake) they have a right to produce a block." [1] La prueba de la VRF viaja en la cabecera y sirve para que los demás verifiquen la reclamación.
La especificación fija el umbral para una autoridad con peso sobre un peso total : . [2] Aquí aparece la constante c, que el código define como un parámetro en [0, 1] "for which 1 - c is the probability of a slot being empty", y advierte que su elección "affects the security of the protocol relating to maximum tolerable network delays." [1]
¿Por qué esa forma exponencial? Porque hace que el resultado no dependa de cómo se reparte el peso. La probabilidad de que una autoridad no gane es . Si los sorteos son independientes, la probabilidad de que no gane nadie es el producto de esos factores, y como los exponentes suman 1, el producto es exactamente . Dividir una autoridad en dos con la mitad del peso cada una no cambia la probabilidad de un slot vacío. Esta deducción es nuestra, a partir de la fórmula de la especificación.
En números concretos: el runtime de referencia del SDK, el nodo kitchensink, usa PRIMARY_PROBABILITY = (1, 4), con el comentario "1 in 4 blocks (on average, not counting collisions) will be primary BABE blocks." [4] Es decir, c = 1/4. Tres de cada cuatro slots, en promedio, no tienen ganador primario. Más abajo veremos qué se hace con ellos.
¿Por qué no elegir c cercano a 1 para llenar todos los slots? Porque cuanto mayor es c, más frecuentes son los slots con dos o más ganadores, y cada uno de esos es un fork temporal que la red tiene que resolver. Un c pequeño deja más tiempo entre bloques primarios para que se propaguen antes del siguiente. Esa es la relación con el retardo de red que menciona el código.
Cuando ganan dos o no gana nadie
Un sorteo independiente por autoridad tiene dos casos incómodos, y el código los nombra sin rodeos: "it is possible that a slot is assigned to multiple validators in which case we will have a temporary fork, or that a slot is assigned to no validator in which case no block is produced." [1] El primero explica el incidente del escenario inicial; el segundo explicaría huecos en la cadena.
Para los huecos, BABE tiene slots secundarios. Si nadie ganó el sorteo primario, el slot tiene un autor de respaldo calculado de forma determinista: el índice blake2_256(epoch_randomness ++ slot_number) % authorities_len. [1] La especificación lo describe como respaldo y aclara que, a diferencia de la lotería, "secondary slot assignees are known upfront publically". [2] El precio del respaldo es volver a la predictibilidad de Aura, pero solo para esos slots.
Los slots secundarios son configurables. El enum AllowedSlots ofrece tres opciones: solo primarios, primarios más secundarios plain, y primarios más secundarios con VRF. [5] La variante con VRF genera una salida adicional que, según el código, "is not included in beacon randomness, but can be consumed by parachains". [1] El nodo kitchensink usa PrimaryAndSecondaryPlainSlots. [6]
La documentación de Polkadot agrega una regla de convivencia: si existe un bloque primario para un slot, el bloque secundario de ese slot se ignora, de modo que "every slot will have either a primary or a secondary block." [7] La figura 1 junta los tres casos.
BABE: un ganador, dos ganadores o ninguno
Cómo leer esta figura
A la izquierda, un recuadro azul con la lotería por slot: la VRF de la autoridad sobre la aleatoriedad de la época y el slot debe ser menor que T igual a uno menos uno menos c elevado a w_a sobre A_w. Una flecha lleva al slot s, con un bloque primario de un solo ganador. De él salen dos flechas al slot s+1, con dos bloques primarios de A1 y A3, marcados como fork temporal. Del bloque de A1 sale una flecha al slot s+2, un bloque secundario en ocre porque nadie ganó, cuyo autor fijo es blake2 de la aleatoriedad y el slot módulo el número de autoridades. Abajo, dos recuadros: el fork choice elige la cadena con más bloques primarios y, en empate, la más larga; al cerrar la época N se anuncian autoridades y aleatoriedad de la época N+2.
Épocas: fijar las reglas antes de jugar
Un sorteo es justo solo si nadie puede elegir la tómbola después de ver el resultado. BABE agrupa los slots en épocas: "An epoch is a contiguous number of slots under which we will be using the same authority set." [1] Dentro de una época, las autoridades, sus pesos y la aleatoriedad que alimenta la VRF están fijos.
El detalle clave es el calendario: "Epoch changes are announced one epoch in advance, i.e. when ending epoch N, we announce the parameters (randomness, authorities, etc.) for epoch N+2." [1] La aleatoriedad de una época se arma con las salidas VRF de los bloques de una época anterior; el código lo describe como un "on-chain randomness pool". [1] La investigación de Web3 Foundation da la razón del desfase: asegurar que las claves VRF de los validadores nuevos estén registradas "before the randomness of the epoch that they are going to be active is revealed." [3]
Dicho de otro modo: si pudieras registrar una clave después de conocer la aleatoriedad, podrías probar claves hasta encontrar una que gane muchos slots. Al exigir que la clave exista antes de que se revele la aleatoriedad, ese atajo desaparece.
Hay una consecuencia operativa que conviene anotar antes de lanzar una red. Las constantes del nodo kitchensink advierten, para la duración del slot y de la época: "Currently it is not possible to change the slot duration after the chain has started. Attempting to do so will brick block production." [4] Estos números se eligen una vez. En Polkadot, la documentación habla de "around 6 seconds per slot", que es un parámetro de despliegue y no una constante del protocolo. [7]
Elegir cadena y castigar la equivocación
Con forks temporales legítimos, hace falta una regla para decidir qué rama seguir. La de BABE no es la cadena más larga a secas: "The fork choice rule is weight-based, where weight equals the number of primary blocks in the chain. We will pick the heaviest chain (more primary blocks) and will go with the longest one in case of a tie." [1] Los bloques secundarios, cuyo autor era público, pesan menos que los que salieron de la lotería secreta.
Esa regla tiene un límite superior: GRANDPA. La documentación de Polkadot lo dice sin matices: "BABE must always build on the chain that GRANDPA has finalized." [7] Ninguna cantidad de bloques primarios justifica abandonar un bloque finalizado. Lo veremos en el capítulo 13.
Queda la conducta maliciosa. La especificación define: "A block producer equivocates if they produce more than one block at the same slot." [2] Ganar un slot da derecho a un bloque, no a varios. El nodo kitchensink configura en pallet_babe un EquivocationReportSystem que conecta esas pruebas con el sistema de ofensas del runtime. [6] El capítulo sobre castigo financiero y slashing explica qué se gana al convertir la prueba en una pérdida económica, y el de vectores de ataque explica por qué la equivocación y los ataques de largo alcance son los enemigos naturales de los protocolos de este tipo.
Comparación
Aura y BABE frente a frente
Aura
Turno fijo y público: A[s mod |A|].
- Fortaleza
- simplicidad
- Riesgo
- ataque dirigido al próximo autor
- Un autor por slot
- Sin forks por diseño
- Autor predecible
- Cadena más larga
BABE
Lotería VRF secreta con respaldo secundario.
- Fortaleza
- autor impredecible
- Riesgo
- forks y elección de c
- Cero, uno o varios ganadores
- Forks temporales legítimos
- Autor oculto hasta publicar
- Más bloques primarios
Qué cambia respecto de Ethereum
En la Beacon Chain de Ethereum cada slot tiene exactamente un proponente, elegido con aleatoriedad del protocolo y ponderado por saldo efectivo, y se puede calcular antes de que el slot empiece; lo vimos en la Beacon Chain. BABE elige ponderando por peso igual que Ethereum, pero cambia dos cosas: el ganador es secreto hasta que publica, y un slot puede tener varios ganadores o ninguno.
La regla de elección de cadena también difiere. Ethereum usa LMD-GHOST, que pesa ramas por los votos más recientes de los validadores, y Casper FFG para finalizar; el capítulo sobre Gasper describe esa combinación. BABE no cuenta votos: cuenta bloques primarios. Los votos llegan después, con GRANDPA, y solo para finalizar.
El patrón general es el mismo: producción probabilística con su propia regla de cadena, más un mecanismo de finalidad aparte que pone un piso. Quien entendió por qué Ethereum separa LMD-GHOST de Casper FFG ya tiene el marco para entender por qué Substrate separa BABE de GRANDPA. El siguiente capítulo, GRANDPA, completa la pareja.
Laboratorio propuesto
Estado: propuesta. Este laboratorio todavía no está publicado en lab.trautslab.dev; se ejecutará en local, sin red pública ni fondos reales.
Objetivo. Medir la lotería de BABE: cuántos bloques son primarios y cuántos secundarios, y cuántos forks temporales aparecen cuando la red se vuelve lenta.
Pasos propuestos.
- Levantar una red local de cuatro nodos con el runtime kitchensink, que trae BABE y GRANDPA.
- Contar bloques primarios y secundarios por época leyendo los digests previos de las cabeceras.
- Provocar latencia con una regla de red (por ejemplo,
tc netemen un contenedor) y medir los forks temporales.
Evidencia esperada. Con c = 1/4 y slots secundarios plain, todos los slots deberían tener bloque y cerca de un cuarto deberían ser primarios, menos los que colisionan. Con latencia alta, más bloques huérfanos en la misma altura y reorganizaciones cortas en los logs. Las cifras exactas dependen del número de autoridades, del hardware y de la versión del nodo, y quedan a validar al construir el laboratorio.
Bibliografía académica
- [1]
Parity Technologies, "sc-consensus-babe: BABE (Blind Assignment for Blockchain Extension)," polkadot-sdk, substrate/client/consensus/babe/src/lib.rs, commit 544e829, 2026.
Lotería VRF por slot, parámetro c, épocas anunciadas con antelación, slots secundarios y fork choice por bloques primarios.
- [2]
Web3 Foundation, "Polkadot Protocol Specification: Block Production," w3f/polkadot-spec, docs/sect-block-production.md, 2025.
BABE basado en Ouroboros Praos, constante de BABE, umbral de victoria y definición de equivocación.
- [3]
Web3 Foundation Research, "BABE," w3f/research, docs/Polkadot/protocols/block-production/Babe.md, 2026.
Diseño de BABE: aleatoriedad por época, ingreso de validadores dos épocas después y diferencias con Ouroboros Praos.
- [4]
Parity Technologies, "Kitchensink node runtime constants," polkadot-sdk, substrate/bin/node/runtime/src/constants.rs, 2026.
PRIMARY_PROBABILITY = (1, 4), duración de slot y de época, y la advertencia de que no se pueden cambiar con la cadena en marcha.
- [5]
Parity Technologies, "sp-consensus-babe: primitives for BABE," polkadot-sdk, substrate/primitives/consensus/babe/src/lib.rs, commit 544e829, 2026.
Enum AllowedSlots: solo primarios, primarios y secundarios plain, primarios y secundarios con VRF.
- [6]
Parity Technologies, "Kitchensink node runtime," polkadot-sdk, substrate/bin/node/runtime/src/lib.rs, 2026.
Configuración de BABE del nodo de referencia: c, slots permitidos y sistema de reporte de equivocaciones.
- [7]
Polkadot Developers, "Proof of Stake Consensus," polkadot-docs, docs/reference/polkadot-hub/consensus-and-security/pos-consensus.md, 2026.
BABE en Polkadot: slots de unos 6 s, varios ganadores, slots sin ganador y relación con GRANDPA.
Rutas vecinas
Si este tema te abrió hambre, sigue por aquí.
Series y labs que comparten área o dependen de esta ruta. Pocas opciones, para no convertir la curiosidad en menú infinito.
Series relacionadas
HotStuff: de cero a estado del arte
Ruta progresiva para entender consenso BFT moderno: quórums, sincronía parcial, locks, taxonomía one/two/three-chain, QC/highQC, multipipeline, view-change, responsiveness, AggQC, Fast-HotStuff, sync y frontera DAG-BFT.
Ethereum: de historia a labs
Serie progresiva para entender Ethereum desde el whitepaper, forks y The Merge hasta EVM, Solidity, proof-of-stake, rollups, account abstraction, DeFi, observabilidad y laboratorios reproducibles.
Ruta práctica: activos digitales en la operación
Nueve módulos, de menor a mayor dependencia, para decidir cómo usar custodia, wallets, llaves, firmas multifirma y MPC, AML/KYT y stablecoins con Fireblocks, BitGo, Kaleido, Circle y Tether.
Labs para convertir lectura en práctica
Prueba de trabajo y reajuste de dificultad
Laboratorio determinista para medir el costo de la prueba de trabajo y ver cómo el reajuste por altura de bloque estabiliza el tiempo entre bloques.
Consensus benchmark
Banco reproducible para comparar consenso BFT y documentar los trade-offs de HotStuff-2.
Ethereum local: Anvil, wallet y primera transacción
Laboratorio base para levantar una red local, crear cuentas, firmar transacciones y observar receipts sin gastar ETH real.
RPC y Cast: leer Ethereum con lupa
Ejercicios con JSON-RPC y Cast para consultar bloques, nonces, gas, receipts, logs y errores reproducibles.
Sigue leyendo
Ideas conectadas con este artículo
Una ruta corta para continuar sin abrir veinte pestañas y perder el hilo.
Producción de bloques por turnos: slots y Aura
Slots, autoridades y turnos: cómo Aura decide quién produce el próximo bloque, qué hace el nodo y qué aporta el runtime, y por qué producir no es finalizar.
GRANDPA: finalizar cadenas, no bloques
El finality gadget de Substrate: rondas de prevote y precommit, supermayorías que se cruzan, accountable safety, justificaciones y cambios de conjunto de autoridades sin detener la finalidad.
Sassafras: un solo productor por slot, en secreto
Sassafras promete el intervalo fijo de Aura con el secreto de BABE. Este capítulo explica el mecanismo de tickets y separa con cuidado lo que existe en el código de lo que es intención de investigación.
Anatomía del consenso en un nodo Substrate
No hay guía oficial para cambiar el consenso de un nodo Substrate. Este capítulo la reconstruye desde el código: por dónde entra un bloque, quién lo verifica, quién lo finaliza y dónde se enchufa cada motor.