Substrate: del runtime al consenso propio

Artículo 5 de 20

25%

completado al llegar aquí

Sistemas distribuidosNota de investigación16 min de lectura

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.

Ruta Substrate: 0/20

La cooperativa del capítulo anterior ya tiene un runtime con su pallet de reservas. Ahora quiere verlo funcionar: crear una cuenta, reservar una sala y ver el evento en un bloque. Nadie en el equipo quiere escribir todavía código de nodo ni elegir un algoritmo de consenso. Necesitan una cadena local, desechable, que produzca bloques en segundos. Este capítulo muestra tres caminos para tenerla y explica la pieza que los une a todos: el chain spec.

Los tres caminos son: el binario polkadot-omni-node con un runtime y un chain spec, un template del SDK (minimal, solochain o parachain) que trae su propio nodo, o el nodo de demostración kitchensink del repositorio. Cada uno cambia cuánto controlas y cuánto código mantienes.

Brújula de lectura

Actor, evidencia y estado

Antes de avanzar, ubica quién actúa, qué prueba queda y qué parte del sistema cambia.

Actor

Quien opera el nodo local

Compila el runtime, genera el chain spec y arranca el binario con un estado temporal.

Evidencia

Hash del génesis

Depende de la raíz de estado inicial: dos nodos con génesis distinto son cadenas distintas.

Estado

Génesis desde un preset

Cuentas con fondos, claves de prueba y el propio :code, todo definido en el chain spec.

Preguntas guía

  • ¿Qué es un nodo "omni" y qué cadenas puede ejecutar?
  • ¿Qué contiene un chain spec y por qué todos los nodos deben usar el mismo génesis?
  • ¿Qué diferencia hay entre los formatos full, patch y raw del génesis?
  • ¿Qué es el sellado manual y por qué sirve para desarrollar pero no para producción?
  • ¿Cuándo necesitas tu propio nodo en lugar del omni-node?

Conexiones dentro de la serie

Nodo y runtime se encuentran: tres caminos

Recordemos la división: el runtime es la STF y el nodo es todo lo demás. La documentación del omni-node lo repite: el nodo contiene base de datos, red, servidor RPC y consenso, y es un binario nativo compilado desde Rust. Durante años, cada runtime venía con su propio nodo, porque ambos estaban fuertemente acoplados; por eso todos los templates traen una carpeta node y otra runtime.

El primer camino rompe ese acoplamiento. polkadot-omni-node es un binario blanco publicado con el SDK, capaz de cubrir las necesidades de la mayoría de las parachains, y también de ejecutar el Wasm de una parachain en local para pruebas. No necesita código propio: se configura con un chain spec externo. La documentación de Polkadot lo describe como capaz de ejecutar "most parachains that do not require custom node-level logic or extensions".

El segundo camino son los templates que se mantienen en el propio repositorio del SDK. El minimal template tiene lo mínimo para ser una cadena funcional y sirve para aprender. El solochain template, antes llamado substrate-node-template, es una cadena independiente con un consenso básico y algunos pallets. El parachain template está listo para conectarse a una relay chain. Si abres el service.rs del nodo solochain, verás que usa Aura para producir bloques y GRANDPA para la finalidad, dos motores con capítulo propio más adelante.

El tercer camino es el nodo kitchensink (substrate-node), que incluye todas las funciones de nodo y runtime del SDK. Su runtime reúne todos los módulos de FRAME, y la documentación avisa que "is only used for testing and demonstration". Sirve para explorar, no como base de un proyecto.

Elegir el camino

¿Con qué nodo empiezo?

Recomendado

polkadot-omni-node

Binario listo; solo aportas el runtime y el chain spec.

Ideal para
Probar la lógica del runtime y desarrollar parachains.
Ojo con
Pensado para parachains: no soporta solochains en producción ni consensos propios.
Precaución

Template (minimal, solochain, parachain)

Código de nodo y runtime en tu repositorio.

Ideal para
Una solochain, o cuando necesitas tocar el nodo: consenso, pool de transacciones.
Ojo con
Mantienes service.rs y sus dependencias en cada versión del SDK.

Nodo kitchensink

Todos los pallets y todas las funciones del nodo.

Ideal para
Explorar BABE, GRANDPA y otros pallets en un solo binario.
Ojo con
Solo para pruebas y demostración, no como base de un proyecto.
La pregunta clave es si necesitas cambiar el nodo. Si no, no lo mantengas.

La documentación del omni-node lo resume en tres opciones para quien construye una parachain: usar polkadot-omni-node, que "can run almost any runtime with --dev-block-time"; usar su librería para tener algo más de control; o usar los nodos tradicionales, la mejor opción para quien quiere control total, "such as changing the consensus engine, altering the transaction pool, and so on". Esta ruta termina conectando un consenso propio, así que más adelante vas a necesitar el tercer camino.

El chain spec: génesis más propiedades de red

Un chain spec (especificación de cadena) es el archivo que le dice a un nodo de qué cadena forma parte. La documentación lo define así: "A chain specification file defines the set of properties that are required to run the node as part of the chain." Tiene dos partes: el estado inicial del runtime y las propiedades de red, de las cuales la más importante es la lista de bootnodes, los nodos conocidos a los que conectarse al arrancar.

El estado inicial se llama génesis. Todos los nodos de una red deben construir sobre exactamente el mismo bloque génesis, y como la cabecera de ese bloque incluye la raíz de estado, cualquier diferencia en el estado inicial produce otra cadena. El génesis puede incluir cuentas con fondos, la cuenta administradora (sudo) y el conjunto inicial de autoridades del consenso. Y como el runtime vive en el estado, el Wasm inicial también va en el chain spec, bajo :code.

El génesis admite tres formatos.

  • full: un JSON con todas las claves de la configuración de génesis del runtime; no se usan valores por defecto.
  • patch: solo las claves que cambian respecto del valor por defecto que provee el runtime. La regla es full = default + patch, con la advertencia de que el valor por defecto puede no funcionar solo.
  • raw: pares clave-valor del almacenamiento ya calculados. El código del runtime es uno de esos pares.

Para pasar de full o patch a raw, el nodo le entrega el JSON al runtime por la runtime API GenesisBuilder::build_state, y el runtime lo convierte en entradas de storage. Por eso el runtime debe implementar esa API. Para cadenas de producción o de larga vida se recomienda raw: es el único formato que garantiza que la raíz de estado no cambie cuando cambia la estructura de la configuración de génesis en una actualización de software.

Figura 1

Del runtime compilado a bloques locales

Fuentes:

[8][7][4]
Del runtime compilado a bloques locales
Cómo leer esta figura

Fila superior de izquierda a derecha: una caja verde crate del runtime, FRAME y Rust; una flecha 1, cargo build, lleva a una caja violeta runtime.wasm compilado; una flecha 2, chain-spec-builder, con el rótulo inferior preset development, lleva a una caja ocre chain_spec.json, génesis más red. De esta baja una flecha 3, guion guion chain, a una caja azul polkadot-omni-node con guion guion dev-block-time 1000. Una flecha azul 4, sella, va hacia la izquierda a la caja un bloque por segundo, manual seal, sin consenso. Desde la caja del runtime baja una flecha roja discontinua rotulada otra ruta: control total hacia una caja roja nodo propio, template solochain, Aura y GRANDPA. Fila inferior con el título sección genesis del chain spec: tres cajas, full: todas las claves; patch: default más cambios; raw: pares clave-valor. Una línea discontinua une full y patch, y una flecha build_state, en el runtime, va de patch a raw.

Visual original de TrautsLab. Se compila el runtime a Wasm, chain-spec-builder genera el chain spec con un preset de génesis y polkadot-omni-node con --dev-block-time sella un bloque por segundo sin consenso. La ruta alternativa es un nodo propio desde el template solochain. Abajo, los tres formatos de la sección genesis.

Presets de génesis: desarrollo frente a red de pruebas

Escribir un génesis a mano es propenso a errores. Por eso los runtimes exponen presets: configuraciones de génesis con nombre, ya preparadas. La documentación los describe como variantes útiles para redes de prueba predefinidas, desarrollo local o pruebas de integración, con cuentas con fondos, autoridades de consenso y clave sudo ya cargadas. Un preset es, en realidad, un patch que se combina con el valor por defecto.

El SDK recomienda que todo runtime exponga al menos dos presets: development, pensado para probar con un solo nodo, y local_testnet, pensado para varios nodos locales. La decisión práctica es simple: development para iterar sobre la lógica en tu máquina; local_testnet cuando quieres ver varios nodos, por ejemplo con herramientas como zombienet; y un chain spec raw, revisado y versionado, para cualquier red que deba durar.

Una advertencia de la documentación ahorra horas de depuración: si construyes un preset a mano en JSON y escribes mal una clave, la deserialización puede ignorarla en silencio. La recomendación es usar la macro build_struct_json_patch y probar cada preset convirtiéndolo a almacenamiento raw.

Sellado manual y la secuencia de la guía oficial

La guía "Your first Node" ejecuta un runtime sin código de consenso. Ese runtime "can only be executed with a node that also expects no consensus", es decir, con sellado manual, y la opción --dev-block-time del omni-node hace precisamente eso. El sellado manual (manual seal) es un motor que, según su código, "listens for rpc calls to seal blocks and create forks" y está pensado para entornos de prueba. Con --dev-block-time, en vez de esperar una llamada RPC, sella un bloque a intervalos fijos.

Flujo visual

Secuencia de la guía oficial (omni-node en modo desarrollo)

Pasos tomados de la guía del SDK; no se ejecutaron para este capítulo.
  1. Instalarpolkadot-omni-node y staging-chain-spec-builder.
  2. Compilarcargo build --release del runtime: produce el .wasm.
  3. Chain specchain-spec-builder con el preset development.
  4. Ejecutaromni-node con --tmp, --dev-block-time y --chain.
  5. ObservarUn bloque por intervalo, sin consenso ni relay chain.

Los comandos de la guía son estos. Se reproducen como referencia: no se ejecutaron para este capítulo, y las versiones deben fijarse según la versión del SDK que uses.

Bash
# Fuente: docs/sdk/src/guides/your_first_node.rs (paritytech/polkadot-sdk). Referencia, no verificado aquí.
cargo install polkadot-omni-node
cargo install staging-chain-spec-builder
 
chain-spec-builder -c <ruta-de-salida> create \
  --relay-chain dontcare \
  --runtime polkadot_sdk_docs_first_runtime.wasm \
  named-preset development
 
polkadot-omni-node --tmp --dev-block-time 1000 --chain <chain_spec>.json

Tres detalles del bloque anterior. El crate se llama staging-chain-spec-builder porque el nombre chain-spec-builder en crates.io ya estaba tomado por otra persona. El omni-node está hecho para parachains, así que el chain spec debe llevar los campos para_id y relay_chain; por eso aparece --relay-chain dontcare. Y --tmp guarda el estado en una carpeta temporal, para reiniciar sin purgar la cadena.

Queda una tensión que conviene nombrar. La documentación del omni-node dice que, por ahora, las solochains no están soportadas por los OmniNodes, pero también que --dev-block-time puede ejecutar cualquier runtime con sellado manual, sin restricciones sobre el consenso del runtime. La lectura prudente: --dev-block-time es un modo de desarrollo para probar lógica, no una forma de operar una solochain. Probarlo con el runtime de la cooperativa antes de escribir el laboratorio de esta ruta queda a validar.

Qué cambia respecto de Ethereum

Si usaste Anvil, la idea es conocida: una cadena local que mina bloques al instante o a intervalos, con cuentas de prueba precargadas, para iterar sin red pública. --dev-block-time con el preset development cumple el mismo papel. La diferencia es qué estás probando. Con Anvil pruebas contratos sobre reglas de Ethereum fijas. Con el omni-node pruebas las reglas mismas: tu runtime es la STF de esa cadena local.

Otra diferencia es el génesis. En Ethereum, el génesis de mainnet está fijado y tus pruebas locales imitan esa cadena. En Substrate, el génesis forma parte de tu diseño: decides cuentas iniciales, autoridades y el Wasm inicial, y lo distribuyes como chain spec. Dos equipos con el mismo runtime pero distinto chain spec operan cadenas distintas.

Por último, el acceso. Como en JSON-RPC de Ethereum, el nodo expone un servidor RPC para clientes; la confianza que depositas en sus respuestas depende de si el nodo es tuyo o de un tercero. En tu máquina, con --tmp, el nodo es tuyo y desechable.

Qué llevarte de este capítulo

Para ver un runtime funcionando no necesitas escribir un nodo: compilas el runtime, generas un chain spec con chain-spec-builder y un preset, y arrancas polkadot-omni-node con --dev-block-time, que sella bloques sin consenso. El chain spec junta génesis y propiedades de red; el formato raw es el que conviene para redes duraderas. Si necesitas cambiar el consenso o el pool de transacciones, el camino es un nodo propio desde un template, y esa es la dirección que tomará esta ruta.

Referencias

Bibliografía académica

Formato IEEENumerado para ingeniería, sistemas y protocolos.
  1. [1]

    Parity Technologies, "(Omni) Node," polkadot_sdk_docs, paritytech/polkadot-sdk, docs/sdk/src/reference_docs/omni_node.rs. [Online]. Available: https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/docs/sdk/src/reference_docs/omni_node.rs (consultado 2026-11-13).

    Tipos de nodo, alcance del omni-node, --dev-block-time y consenso compartido entre nodo y runtime.

  2. [2]

    Polkadot Developers, "Polkadot Omni Node," polkadot-developers/polkadot-docs, docs/reference/tools/omninode.md. [Online]. Available: https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/docs/reference/tools/omninode.md (consultado 2026-11-13).

    El omni-node se configura con un chain spec externo.

  3. [3]

    Parity Technologies, "Templates," polkadot_sdk_docs, paritytech/polkadot-sdk, docs/sdk/src/polkadot_sdk/templates.rs. [Online]. Available: https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/docs/sdk/src/polkadot_sdk/templates.rs (consultado 2026-11-13).

    Templates minimal, solochain (antes substrate-node-template) y parachain.

  4. [4]

    Parity Technologies, "Solochain template: node service," paritytech/polkadot-sdk, templates/solochain/node/src/service.rs. [Online]. Available: https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/templates/solochain/node/src/service.rs (consultado 2026-11-13).

    source codeID: SOLOCHAIN-SERVICEAbrir fuente (abre en otra pestaña)

    El nodo del template solochain conecta sc_consensus_aura (import queue) y sc_consensus_grandpa (block import).

  5. [5]

    Parity Technologies, "Polkadot SDK," polkadot_sdk_docs, paritytech/polkadot-sdk, docs/sdk/src/polkadot_sdk/mod.rs. [Online]. Available: https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/docs/sdk/src/polkadot_sdk/mod.rs (consultado 2026-11-13).

    Componentes del Polkadot SDK: Substrate, FRAME, Cumulus, XCM y binarios.

  6. [6]

    Parity Technologies, "Chain Spec Genesis," polkadot_sdk_docs, paritytech/polkadot-sdk, docs/sdk/src/reference_docs/chain_spec_genesis.rs. [Online]. Available: https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/docs/sdk/src/reference_docs/chain_spec_genesis.rs (consultado 2026-11-13).

    Qué es un chain spec, GenesisConfig, presets y formatos de génesis.

  7. [7]

    Parity Technologies, "sc-chain-spec," paritytech/polkadot-sdk, substrate/client/chain-spec/src/lib.rs. [Online]. Available: https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/substrate/client/chain-spec/src/lib.rs (consultado 2026-11-13).

    source codeID: SC-CHAIN-SPECAbrir fuente (abre en otra pestaña)

    Campos del chain spec y formatos full, patch y raw.

  8. [8]

    Parity Technologies, "Your first Node," polkadot_sdk_docs, paritytech/polkadot-sdk, docs/sdk/src/guides/your_first_node.rs. [Online]. Available: https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/docs/sdk/src/guides/your_first_node.rs (consultado 2026-11-13).

    Pasos: instalar omni-node y chain-spec-builder, compilar runtime, crear chain spec y ejecutar.

  9. [9]

    Parity Technologies, "sp-genesis-builder," paritytech/polkadot-sdk, substrate/primitives/genesis-builder/src/lib.rs. [Online]. Available: https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/substrate/primitives/genesis-builder/src/lib.rs (consultado 2026-11-13).

    source codeID: SP-GENESIS-BUILDERAbrir fuente (abre en otra pestaña)

    Presets development (un nodo) y local_testnet (varios nodos locales).

  10. [10]

    Parity Technologies, "sc-consensus-manual-seal," paritytech/polkadot-sdk, substrate/client/consensus/manual-seal/src/lib.rs. [Online]. Available: https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/substrate/client/consensus/manual-seal/src/lib.rs (consultado 2026-11-13).

    source codeID: SC-MANUAL-SEALAbrir fuente (abre en otra pestaña)

    Motor de sellado manual para entornos de prueba.

Fuentes primarias, papers seminales y especificaciones técnicas citadas en esta investigación.

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.

Sigue leyendo

Ideas conectadas con este artículo

Una ruta corta para continuar sin abrir veinte pestañas y perder el hilo.

Los comentarios se cargan al final de la lectura para no meter peso antes de tiempo.