Substrate: del runtime al consenso propio
Artículo 19 de 20
95%
completado al llegar aquí
Sistemas distribuidosNota de investigación21 min de lectura
Anatomía del consenso en un nodo Substrate
El recorrido de un bloque por el nodo, leído en el código del Polkadot SDK: import queue, BlockImport, fork choice, justificaciones, finalidad y autoría.
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.
Tu primer nodo local: templates, omni-node y chain spec
Tres caminos para levantar una cadena Substrate local: polkadot-omni-node con chain spec, un template o el nodo kitchensink, y qué guarda el génesis.
Blockchain16 min de lectura→Producción de bloques por turnos: slots y Aura
Cómo Substrate divide el tiempo en slots, por qué Aura asigna cada slot a A[s mod |A|] y qué falta para que esos bloques sean definitivos.
Blockchain17 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.
Blockchain18 min de lectura→GRANDPA: finalizar cadenas, no bloques
Cómo GRANDPA finaliza prefijos de cadena con prevotes, precommits y 2/3-GHOST, por qué tolera f < n/3 y qué pasa cuando la finalidad se detiene.
Blockchain18 min de lectura→Ponerse al día: full, fast y warp sync; light clients
Cómo un nodo nuevo llega al estado actual de una cadena Substrate sin confiar en un peer: full, fast y warp sync, justificaciones GRANDPA y light clients.
Blockchain15 min de lectura→
Una mañana, un nodo de una red privada construida con Substrate (Polkadot SDK) deja de finalizar. Sigue importando bloques de Aura, la altura sube, pero el último bloque final no se mueve. En los logs aparece un aviso de GRANDPA sobre una justificación que no se pudo importar. El equipo de guardia tiene que responder rápido: ¿el problema está en la red, en la import queue, en la cadena de BlockImport o en el voter de GRANDPA? Para contestar hace falta un mapa del nodo.
Este capítulo dibuja ese mapa. Sigue un bloque desde que llega por red hasta que una notificación anuncia que es final, y otro desde que el nodo decide producirlo. En cada tramo nombra el tipo de Rust que lo implementa y el archivo donde leerlo. Es el capítulo que prepara el capstone: conectar un consenso propio exige saber qué pieza se reemplaza y cuál se conserva.
Brújula de lectura
Actor, evidencia y estado
Actor
Tareas del nodo: import queue, slot worker, voterCada motor de consenso es un conjunto de tareas y envoltorios que el servicio del nodo cablea.
Evidencia
Sello en la cabecera y justificación aparteEl sello prueba quién produjo el bloque; la justificación prueba que es final.
Estado
Mejor bloque y último bloque finalizadoDos punteros distintos en la base de datos del cliente, movidos por piezas distintas.
Preguntas guía
- ¿Qué hace la import queue y en qué se diferencia de la cadena de
BlockImport? - ¿Dónde se decide cuál es el mejor bloque y dónde cuál es el último final?
- ¿Qué es exactamente una justificación en el código y por qué no va dentro del bloque?
- ¿Qué tiene que coincidir entre el nodo y el runtime para que un motor funcione?
Conexiones dentro de la serie
- Antes: Tu primer nodo local, Slots y Aura, BABE, GRANDPA y Sincronización y light clients explicaron cada motor por separado. BEEFY mostró un envoltorio de importación más.
- Investigación relacionada: Substrate y HotStuff: sincronizar cuando finalizas rápido describe una integración que tocó sync y finalidad. Taxonomía de reglas de commit resume las reglas que un motor nuevo debe respetar al importar. DiemBFT, Jolteon y Ditto en producción muestra qué cambia cuando un protocolo BFT sale del paper.
- Después: Capstone: un consenso BFT propio.
Sin guía oficial: leer el código
Lo primero que conviene saber es incómodo. La documentación del SDK tiene un archivo docs/sdk/src/guides/changing_consensus.rs, pero su único contenido es el título # Changing Consensus. [1] No hay un tutorial oficial paso a paso para cambiar el consenso de un nodo. Este capítulo trabaja, por tanto, desde el código fuente y la documentación en línea de los crates.
El inventario sí está documentado. La página de Substrate en el SDK lista "All of the consensus related crates provided by Substrate": Aura, BABE, GRANDPA, BEEFY, manual seal y prueba de trabajo. [2] Todos se apoyan en dos crates comunes: sc-consensus (import queue, block import, LongestChain) y sp-consensus (Environment, Proposer, SelectChain).
La regla que más errores evita está en la documentación del omni node: "In any given substrate-based chain, both the node and the runtime will have their own opinion/information about what consensus engine is going to be used." [3] La mayor parte del motor vive en el nodo, pero el runtime expone una runtime API propia del motor, implementada por su pallet. La conclusión del documento va en negrita: nodo y runtime "must have matching consensus components."
En la práctica, esa regla tiene dos caras. Si el nodo ejecuta Aura y el runtime no implementa AuraApi, el nodo no puede saber la duración del slot ni las autoridades. Si el runtime incluye pallet_grandpa pero el nodo no arranca el voter, la cadena produce bloques y nunca finaliza: exactamente el síntoma del escenario.
La puerta de entrada: import queue y Verifier
Todo bloque ajeno entra por la import queue. El código la define como "an intermediate and abstracted step between synchronization and import. Each mode of consensus will have its own requirements for block verification." [4] Sync le entrega bloques como IncomingBlock, que pueden traer cabecera, cuerpo y justificaciones.
La pieza que cada motor aporta es el Verifier, un trait de un solo método: verificar los datos del bloque y "return the BlockImportParams to continue the block import process." [4] El verificador no guarda nada: comprueba lo que se puede comprobar sin ejecutar el bloque y prepara los parámetros para el siguiente tramo.
El verificador de Aura es un buen ejemplo. Comprueba el sello de la cabecera contra la autoridad del slot y, si es válido, quita el sello de la cabecera, lo añade a post_digests y fija la estrategia de fork choice en LongestChain. [5] Sus errores dicen qué falló: cabecera sin sello, sello inválido, firma inválida o autor del slot no encontrado.
¿Por qué quitar el sello? Porque el runtime no debe verlo. El código de BlockImportParams lo explica: los motores que alteran la cabecera con digests posteriores al runtime "should strip those off in the initial verification process and pass them via the post_digests field." [6] Así la cabecera puede reejecutarse tal como salió del runtime, y el sello se vuelve a poner después.
Los digests tienen cuatro variantes relevantes en sp-runtime: PreRuntime (del motor al runtime, como el slot), Consensus (del runtime al motor, como un cambio de autoridades), Seal (solo del código nativo, nunca visto por el runtime) y RuntimeEnvironmentUpdated. [7] Cada variante lleva un ConsensusEngineId de cuatro bytes que identifica al motor.
La cadena de BlockImport
Tras el verificador, los BlockImportParams recorren una cadena de objetos que implementan el trait BlockImport, con dos métodos: check_block e import_block. [6] Cada eslabón envuelve al siguiente; el último es el propio cliente, que ejecuta el runtime y escribe en la base de datos.
Los campos de BlockImportParams son el contrato entre eslabones. Los que importan para el consenso:
justifications: "Justification(s) provided for this block from the outside."finalized: si el bloque ya es final;true"implies instant finality".fork_choice: la estrategia para decidir si es el nuevo mejor bloque.intermediates: valores que un eslabón deja para otro; cada uno debe consumir los suyos, y el último rechaza la importación si queda alguno sin tratar.
El patrón de envoltorio es el que usa GRANDPA. Su crate lo exige sin matices: "All blocks imported (from network or consensus or otherwise) must pass through this wrapper, otherwise consensus is likely to break in unexpected ways." [8] El envoltorio inspecciona cada bloque en busca de señales de cambio de autoridades. Si un bloque aplica un cambio y el conjunto actual ya no está vivo, el bloque debe traer una justificación válida. [9]
La consecuencia práctica es una regla de cableado: el mismo objeto envuelto se usa en la import queue y en la autoría. Si el bloque propio se importara saltándose el envoltorio, GRANDPA no vería sus cambios de autoridades. BEEFY, en el nodo kitchensink, añade un eslabón más por encima del de GRANDPA. [10]
Mejor bloque y bloque final: dos decisiones
El nodo mantiene dos punteros distintos. El mejor bloque se decide al importar, con ForkChoiceStrategy: LongestChain o Custom(bool), donde el booleano es una regla propia: "true indicates the new block should be the best block." [6] Si nadie fija la estrategia, la importación falla: el campo None exige que un eslabón posterior lo complete.
El trait SelectChain responde una pregunta parecida desde fuera de la importación: entre las hojas de la cadena, cuál es la mejor para construir encima y cuál conviene intentar finalizar. Su documentación separa ambos usos: la estrategia "can be customized for the two use cases of authoring new blocks upon the best chain or which fork to finalize." [11] El template usa LongestChain, y GRANDPA lo recibe para elegir hacia dónde votar.
El último bloque final no lo mueve la importación normal, sino una justificación. En sp-runtime, una justificación es una pareja (ConsensusEngineId, EncodedJustification): un identificador de motor de cuatro bytes y una prueba opaca. [12] GRANDPA usa el identificador FRNK. Un bloque puede tener varias justificaciones de motores distintos.
¿Por qué no va dentro del bloque? La documentación lo explica: si hay varias pruebas válidas, incluirlas en el bloque permitiría cambiar su hash intercambiando justificaciones, "and thus fork the chain". [12] Por eso viaja al lado del bloque, por sync, y se guarda aparte.
Justificaciones, finalidad y notificaciones
Una justificación puede llegar por dos caminos. El primero es el voter local: cuando GRANDPA concluye una ronda, finaliza el bloque y guarda su justificación. El segundo es la red: un par envía un bloque con justificación o la justificación sola. Para ese caso existe el trait JustificationImport, cuyo método import_justification debe "Import a Block justification and finalize the given block." [6]
La import queue también puede pedir justificaciones. El trait Link reúne los "Hooks that the verification queue can use to influence the synchronization algorithm", entre ellos request_justification. [4] El resultado de importar un bloque, ImportedAux, tiene banderas para ello: needs_justification y bad_justification. Así un envoltorio como el de GRANDPA dice "este bloque cambia autoridades, consigue su justificación".
Finalizar es una operación del cliente. El trait Finalizer documenta que finalizar un bloque "will implicitly finalize all blocks up to it and fire finality notifications." [13] Si se pasa una justificación, se guarda con ese bloque; los antecesores quedan finales sin justificación propia.
Quien necesite reaccionar a la finalidad se suscribe. El cliente ofrece import_notification_stream y finality_notification_stream, con una advertencia que cualquier integración debe leer: la segunda "Not guaranteed to be fired for every finalized block." [14] Cada FinalityNotification incluye la ruta de bloques finalizados implícitamente; un consumidor que solo mire el hash final perderá bloques intermedios.
Volviendo al escenario: un aviso de justificación no importada, con bloques que siguen entrando, apunta al tramo de JustificationImport o al voter, no a la import queue de bloques. Ese diagnóstico solo es posible con el mapa.
Autoría: slot worker, Environment y Proposer
Producir un bloque propio es el camino inverso. En Aura, una tarea de slot worker se despierta en cada slot, comprueba si la clave local es la autoridad del turno y, si lo es, pide un bloque. El crate de slots permite además frenar la autoría cuando la finalidad se atrasa: "An example strategy that back offs if the finalized head is lagging too much behind the tip is implemented by [BackoffAuthoringOnFinalizedHeadLagging]." [15] El solochain template la deja desactivada.
El bloque lo arma un Proposer, creado por un Environment. sp-consensus describe al proposer como lógica que encapsula la creación de propuestas sobre un bloque padre, y añade: "Proposers are generic over bits of “consensus data” which are engine-specific." [16] El proposer básico (sc-basic-authorship) toma transacciones del pool, ejecuta el runtime y devuelve el bloque con sus cambios de almacenamiento.
El motor añade lo suyo antes y después: el digest PreRuntime con el slot y, al final, el sello firmado. Después, el bloque sellado entra por la misma cadena de BlockImport que los bloques ajenos. Esa simetría es deliberada: el envoltorio de GRANDPA ve igual un bloque propio que uno de la red.
El cableado completo en el solochain template
Todo lo anterior se ve junto en un archivo: templates/solochain/node/src/service.rs. [17] El fragmento siguiente lo resume; se han quitado tipos genéricos, telemetría y proveedores de inherentes.
// Fragmento ilustrativo, simplificado de templates/solochain/node/src/service.rs (polkadot-sdk)
let select_chain = sc_consensus::LongestChain::new(backend.clone());
// 1. El envoltorio de GRANDPA y su enlace con el voter.
let (grandpa_block_import, grandpa_link) = sc_consensus_grandpa::block_import(
client.clone(), GRANDPA_JUSTIFICATION_PERIOD, &client, select_chain.clone(), telemetry,
)?;
// 2. Import queue de Aura: verifica sellos e importa a través del envoltorio.
let import_queue = sc_consensus_aura::import_queue(ImportQueueParams {
block_import: grandpa_block_import.clone(),
justification_import: Some(Box::new(grandpa_block_import.clone())),
client: client.clone(),
/* inherentes (timestamp, slot), spawner, métricas */
})?;
// 3. Autoría con Aura (solo si el nodo es autoridad).
let aura = sc_consensus_aura::start_aura(StartAuraParams {
block_import, proposer_factory, select_chain,
justification_sync_link: sync_service.clone(),
/* duración del slot, keystore, sync_oracle, ... */
})?;
// 4. Finalidad: el voter de GRANDPA como tarea esencial.
sc_consensus_grandpa::run_grandpa_voter(GrandpaParams { link: grandpa_link, network, /* ... */ })?;Cuatro detalles merecen atención. El envoltorio de GRANDPA aparece dos veces en la import queue: como block_import y como justification_import. La autoría recibe el mismo block_import. El voter recibe el grandpa_link, que conecta su estado con el del envoltorio. Y la constante GRANDPA_JUSTIFICATION_PERIOD vale 512: cada cuántos bloques, como mínimo, se generan e importan justificaciones.
El servicio también registra el protocolo de notificaciones de GRANDPA en la red y un proveedor de pruebas para warp sync construido con el conjunto de autoridades de GRANDPA. Ese último detalle conecta con el capítulo de sincronización: warp sync depende de las justificaciones de los cambios de autoridades, y por eso el template instala un filtro de poda específico de GRANDPA.
El recorrido de un bloque por un nodo Substrate con Aura y GRANDPA
Cómo leer esta figura
Primera fila, importación: Red y sync con bloques y justificaciones, flecha a Import queue cuyo Verifier revisa el sello Aura, flecha al envoltorio GRANDPA, un BlockImport que vigila cambios de autoridades, y flecha al Cliente, que ejecuta el runtime, guarda y elige el mejor bloque. Segunda fila, autoría: Slot worker de Aura que pregunta si le toca el slot, flecha al Proposer que arma el bloque con el runtime, y una flecha que sube hasta el envoltorio GRANDPA con la etiqueta sella e importa. Tercera fila, finalidad: Voter GRANDPA con rondas por gossip, flecha a Justificación (FRNK, bytes), flecha a finalize_block, que guarda la justificación, y flecha a Notificación de finalidad. Una flecha discontinua baja del Cliente a la Notificación con la etiqueta el mismo cliente emite importación y finalidad.
Flujo visual
Qué reemplazar y qué conservar al cambiar un motor
Qué cambia respecto de Ethereum
En Ethereum después de The Merge, la separación entre producir y ejecutar es una frontera entre procesos: un cliente de consenso y un cliente de ejecución que hablan por la Engine API, como explica el capítulo sobre ejecución y consenso. Cambiar el consenso de Ethereum es cambiar la especificación de toda la red.
En Substrate, la frontera está dentro de un mismo binario: el runtime ejecuta, y las tareas del nodo producen, importan y finalizan. Cambiar el consenso es cambiar qué tareas y envoltorios cablea el servicio, más el pallet y la runtime API del motor. La flexibilidad es mucho mayor, y también la responsabilidad: no hay una especificación externa que te diga si tu cableado es correcto.
La regla de fork choice también se reparte de otra forma. En Ethereum, Gasper combina LMD-GHOST y Casper FFG en una regla única de la especificación. En Substrate, la mejor cadena se decide al importar (ForkChoiceStrategy), la elección para autoría y finalidad la hace SelectChain, y la finalidad la decide un gadget aparte. Cada pieza es reemplazable por separado.
Laboratorio propuesto
Estado: propuesta. Este laboratorio todavía no está publicado en lab.trautslab.dev; describe lo que se construirá, en local, sin red pública ni fondos reales.
Objetivo. Seguir un bloque por el pipeline completo y ver qué piezas cambian al sustituir el motor de producción.
Pasos propuestos.
- Partir del solochain template con dos autoridades locales y arrancar los nodos con logs detallados de sync, import queue, Aura y GRANDPA (por ejemplo, con la opción
-ly los objetivos de log de cada crate). - Elegir un bloque y seguirlo: anuncio por red, verificación del sello, importación, nuevo mejor bloque, voto de GRANDPA y notificación de finalidad. Anotar la marca de tiempo de cada evento.
- Sustituir Aura por manual seal en el servicio del nodo, producir bloques con la llamada RPC
engine_createBlocky anotar qué piezas del cableado cambian y cuáles se conservan.
Evidencia esperada. Una línea de tiempo por bloque con al menos cinco eventos, en el orden del diagrama, y una diferencia entre importación y finalidad del orden de varios bloques. En el paso 3, un servicio sin slot worker ni verificador de Aura, con la import queue de manual seal y el resto del cableado intacto. Los objetivos de log exactos y el comportamiento de GRANDPA con manual seal quedan a validar al construir el laboratorio.
Bibliografía académica
- [1]
Parity Technologies, "polkadot_sdk_docs: Changing Consensus (guía vacía)," polkadot-sdk, docs/sdk/src/guides/changing_consensus.rs, commit 544e829, 2026.
El archivo solo contiene el título; no hay guía oficial paso a paso para cambiar el consenso.
- [2]
Parity Technologies, "polkadot_sdk_docs: Substrate," polkadot-sdk, docs/sdk/src/polkadot_sdk/substrate.rs, commit 544e829, 2026.
Lista de crates de consenso y precedente de cadenas con componentes de nodo propios.
- [3]
Parity Technologies, "polkadot_sdk_docs: (Omni) Node," polkadot-sdk, docs/sdk/src/reference_docs/omni_node.rs, commit 544e829, 2026.
Nodo y runtime deben coincidir en el motor de consenso; runtime API del motor; opciones de autoría y finalidad.
- [4]
Parity Technologies, "sc-consensus: import queue," polkadot-sdk, substrate/client/consensus/common/src/import_queue.rs, commit 544e829, 2026.
ImportQueue, ImportQueueService, Verifier, IncomingBlock con justificaciones y Link con request_justification.
- [5]
Parity Technologies, "sc-consensus-aura: import queue," polkadot-sdk, substrate/client/consensus/aura/src/import_queue.rs, commit 544e829, 2026.
Verificador de Aura: errores de sello, paso del sello a post_digests y fork_choice LongestChain.
- [6]
Parity Technologies, "sc-consensus: block import," polkadot-sdk, substrate/client/consensus/common/src/block_import.rs, commit 544e829, 2026.
BlockImportParams (post_digests, justifications, finalized, fork_choice, intermediates), ImportedAux, BlockImport, JustificationImport, JustificationSyncLink.
- [7]
Parity Technologies, "sp-runtime: generic digest," polkadot-sdk, substrate/primitives/runtime/src/generic/digest.rs, commit 544e829, 2026.
Variantes de DigestItem: PreRuntime, Consensus, Seal, RuntimeEnvironmentUpdated.
- [8]
Parity Technologies, "sc-consensus-grandpa," polkadot-sdk, substrate/client/consensus/grandpa/src/lib.rs, commit 544e829, 2026.
Envoltorio de block import obligatorio, LinkHalf, run_grandpa_voter, cambios de conjunto de autoridades; crate inestable.
- [9]
Parity Technologies, "sc-consensus-grandpa: import," polkadot-sdk, substrate/client/consensus/grandpa/src/import.rs, commit 544e829, 2026.
GrandpaBlockImport: escaneo de cambios de autoridades e importación de justificaciones con finalización.
- [10]
Parity Technologies, "Kitchensink node service," polkadot-sdk, substrate/bin/node/cli/src/service.rs, commit 544e829, 2026.
Servicio con BABE, GRANDPA y BEEFY: cadena de importación con BeefyBlockImport sobre GRANDPA.
- [11]
Parity Technologies, "sp-consensus: SelectChain," polkadot-sdk, substrate/primitives/consensus/common/src/select_chain.rs, commit 544e829, 2026.
SelectChain: leaves, best_chain y finality_target; distinción entre autoría y finalización.
- [12]
Parity Technologies, "sp-runtime: Justification y Justifications," polkadot-sdk, substrate/primitives/runtime/src/lib.rs, commit 544e829, 2026.
Justification como (ConsensusEngineId, EncodedJustification); por qué viaja fuera del bloque; varias por bloque.
- [13]
Parity Technologies, "sc-client-api: backend (Finalizer)," polkadot-sdk, substrate/client/api/src/backend.rs, commit 544e829, 2026.
Finalizer: apply_finality y finalize_block, justificación guardada con el bloque final, notificaciones de finalidad.
- [14]
Parity Technologies, "sc-client-api: client," polkadot-sdk, substrate/client/api/src/client.rs, commit 544e829, 2026.
Flujos de notificaciones de importación y de finalidad; FinalityNotification con ruta de bloques finalizados implícitamente.
- [15]
Parity Technologies, "sc-consensus-slots," polkadot-sdk, substrate/client/consensus/slots/src/lib.rs, commit 544e829, 2026.
Slots, SlotWorker y estrategia de back-off cuando la finalidad se atrasa.
- [16]
Parity Technologies, "sp-consensus: Environment, Proposer y BlockOrigin," polkadot-sdk, substrate/primitives/consensus/common/src/lib.rs, commit 544e829, 2026.
Environment crea proposers; Proposer genérico sobre datos de consenso; BlockOrigin incluye WarpSync y GapSync; crate inestable.
- [17]
Parity Technologies, "Solochain template: node service," polkadot-sdk, templates/solochain/node/src/service.rs, commit 544e829, 2026.
Cableado de Aura y GRANDPA: block_import de GRANDPA, import queue de Aura con justification_import, warp sync, start_aura y run_grandpa_voter.
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.
BABE: una lotería VRF para producir bloques
La lotería secreta de BABE: umbral por peso, constante c, slots primarios y secundarios, épocas que fijan la aleatoriedad con antelación y una regla de cadena que cuenta bloques primarios.
Ponerse al día: full, fast y warp sync; light clients
Full sync re-ejecuta todo, warp sync salta de un conjunto de autoridades al siguiente con justificaciones GRANDPA, y un light client verifica pruebas de estado en vez de creerle a un RPC.