Substrate: del runtime al consenso propio
Artículo 16 de 20
80%
completado al llegar aquí
Sistemas distribuidosNota de investigación18 min de lectura
XCM: un lenguaje de intenciones entre sistemas de consenso
Qué es XCM en el Polkadot SDK: programas que ejecuta la XCVM, ubicaciones relativas, reserva frente a teletransporte y la confianza que fija el executor.
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.
Extrinsics: transacciones firmadas, sin firmar e inherentes
Qué entra a un bloque Substrate desde fuera del runtime, cómo se codifica un extrinsic versión 5 y qué comprueban las transaction extensions antes de ejecutarlo.
Blockchain16 min de lectura→Parachains con Cumulus: seguridad compartida
Qué cambia cuando una cadena Substrate deja de finalizarse sola: collators, PoV, función de validación, respaldo e inclusión en la relay chain y proof_size.
Blockchain16 min de lectura→
Dos equipos operan parachains distintas sobre la misma relay chain. El primero emite un token de fidelidad; el segundo quiere aceptarlo como pago. Nadie quiere copiar el código del otro ni compartir claves. La pregunta del segundo equipo es concreta: cuando llegue un mensaje que diga "deposita 100 unidades en la cuenta de Bob", ¿por qué habría de creerle? ¿Quién respalda esas 100 unidades?
Este capítulo responde esa pregunta con XCM (Cross-Consensus Messaging), el formato de mensajes del Polkadot SDK. Al terminar deberías poder leer un programa XCM, distinguir una transferencia por reserva de un teletransporte y señalar en la configuración del runtime el lugar exacto donde una cadena decide en quién confía.
Brújula de lectura
Actor, evidencia y estado
Actor
La XCVM de la cadena receptoraEl executor del runtime destino interpreta el programa; la cadena origen solo lo envía.
Evidencia
El origen del mensaje y la configuración del executorNo viaja una prueba criptográfica del activo: la cadena receptora decide si confía en el origen.
Estado
Saldos en las dos cadenas y el Holding RegisterLos activos pasan por un registro temporal de la XCVM antes de llegar al beneficiario.
Preguntas guía
- ¿Por qué XCM se define como un lenguaje y no como un protocolo de red?
- ¿Qué hace la XCVM con cada instrucción y dónde quedan los activos mientras tanto?
- ¿Qué diferencia de confianza hay entre una transferencia por reserva y un teletransporte?
- ¿En qué tipos del executor se declara esa confianza?
Conexiones dentro de la serie
- Antes: Parachains con Cumulus explica cómo una parachain hereda la seguridad de la relay chain. Extrinsics explica cómo entra una orden firmada en un runtime; XCM es la forma de que esa orden cruce a otra cadena.
- Después: Sassafras vuelve al consenso de producción de bloques, y BEEFY trata la mitad que XCM no resuelve: probar finalidad ante una cadena externa.
- Riesgo entre cadenas: Puentes y riesgo cross-chain en Ethereum explica de dónde vienen las pérdidas cuando dos sistemas confían mal el uno en el otro.
Un lenguaje, no un transporte
La documentación del SDK define XCM sin rodeos: "XCM, or Cross-Consensus Messaging, is a language to communicate intentions between consensus systems." [1] Tres palabras pesan en esa frase. Lenguaje: hay una sintaxis y una semántica. Intenciones: el mensaje expresa lo que el emisor quiere, no lo que el receptor está obligado a hacer. Sistemas de consenso: el destinatario puede ser una cadena, un pallet o una cuenta, no solo otra parachain.
La guía de Polkadot Docs lo dice desde el ángulo contrario: "XCM is not a protocol but a standardized messaging format". [2] El formato define la estructura y el comportamiento de los mensajes, pero no su entrega. Esa separación es la idea central del capítulo.
Una analogía útil es una orden de pago escrita en un idioma común. El idioma no dice si la carta viaja por correo o por mensajero, ni obliga al banco receptor a pagar. El banco paga si reconoce al remitente y si la orden tiene sentido según sus propias reglas. XCM funciona igual: el programa es la carta, el canal entre cadenas es el correo y la configuración del runtime receptor es la política del banco.
La misma guía enumera cuatro principios: asíncrono, absoluto, asimétrico y agnóstico. [2] El tercero tiene consecuencias de diseño: un mensaje es "fire and forget" y el emisor no recibe respuesta automática. Si necesitas saber cómo terminó, el destino tiene que enviar otro mensaje de vuelta. El segundo, la garantía de entrega ordenada y oportuna, es una afirmación de la documentación sobre el ecosistema Polkadot, no una propiedad del formato; depende del transporte concreto y queda a validar para cada canal.
La XCVM y el Holding Register
"XCM is executed on a virtual machine called the XCVM." [1] Un programa XCM es una lista de instrucciones que la máquina ejecuta una tras otra. La máquina tiene registros; el más importante para activos es el Holding Register, un lugar temporal donde quedan los activos entre una instrucción y la siguiente.
El ejemplo canónico del SDK es una transferencia local en tres pasos. El fragmento viene de docs/sdk/src/polkadot_sdk/xcm.rs, sin cambios salvo el comentario:
// Fragmento de docs/sdk/src/polkadot_sdk/xcm.rs (polkadot-sdk)
let _transfer_program = Xcm::<()>(vec![
WithdrawAsset((Here, 100u128).into()),
BuyExecution { fees: (Here, 100u128).into(), weight_limit: Unlimited },
DepositAsset {
assets: All.into(),
beneficiary: AccountId32 { id: [0u8; 32].into(), network: None }.into(),
},
]);WithdrawAsset saca activos de la cuenta del origen y los pone en el Holding Register. BuyExecution usa parte de esos activos para pagar el peso de ejecución, el mismo concepto de pesos y comisiones que ya conoces. DepositAsset mueve lo que queda a la cuenta del beneficiario. [3] El orden importa: sin BuyExecution, el destino no tiene por qué gastar cómputo en tu programa.
Las instrucciones no las inventa cada cadena. El tipo Instruction vive en el crate xcm, y en el código actual latest apunta a la versión 5 del formato. Qué versión acepta una cadena concreta en producción es una decisión de su runtime y queda a validar caso por caso.
El SDK reparte la implementación en piezas con nombre propio: xcm define tipos e instrucciones, xcm_executor implementa la máquina virtual, pallet_xcm es el pallet FRAME que permite a los usuarios interactuar con el executor y xcm_builder reúne tipos para configurarlo. [1] Para un ingeniero de runtime, la pieza que más decisiones contiene es la configuración del executor, que veremos más abajo.
Ubicaciones: direcciones relativas
Para decir "la cuenta de Bob en la parachain 2000" hace falta un sistema de direcciones. XCM usa Location, que el código describe como "A relative path between state-bearing consensus systems." [4]
Una ubicación tiene dos partes. Primero, un número de parents: cuántas veces hay que subir al sistema que contiene al actual. Después, una lista de junctions: los pasos para bajar dentro de ese sistema hasta una parte concreta del estado. Desde una parachain, (1, [Parachain(2000)]) significa "sube a la relay chain y baja a la parachain 2000". Desde la relay chain, la misma parachain es (0, [Parachain(2000)]).
La consecuencia práctica es que una ubicación no es un identificador universal. El código lo advierte: no puede usarse en general para referirse a una ubicación de forma universal. [4] Un error frecuente al empezar es copiar una ubicación escrita desde el punto de vista de una cadena y usarla en otra. La transferencia no se pierde: se dirige a otro lugar o falla.
Here, que aparece en el ejemplo anterior, es la ubicación vacía: el propio sistema que interpreta el mensaje. Por eso (Here, 100u128) significa "100 unidades del activo nativo de esta cadena". El mismo activo, visto desde otra parachain, tendría otra ubicación.
Reserva frente a teletransporte
Mover un activo entre cadenas que no comparten estado obliga a elegir un modelo de confianza. XCM ofrece dos, y la diferencia está escrita en las notas de seguridad de dos instrucciones.
En una transferencia por reserva, una cadena R guarda el activo real y las demás tienen derivados respaldados por él. Cuando llega ReserveAssetDeposited, el código exige: "origin must be trusted to have received and be storing assets such that they may later be withdrawn should this system send a corresponding message." [3] Es decir, la cadena destino acuña un derivado porque confía en que la reserva custodia el original.
En un teletransporte, el origen destruye el activo y el destino lo crea de nuevo. La instrucción ReceiveTeleportedAsset exige que "origin must be trusted to have irrevocably destroyed the corresponding assets prior as a consequence of sending this message." [3] Si el origen miente, el destino emite activos sin respaldo. Por eso el teletransporte solo tiene sentido entre cadenas que confían plenamente la una en la otra.
Formato, transporte y confianza en XCM
Cómo leer esta figura
Fila superior: tres cajas conectadas por flechas, Formato (programa XCM con instrucciones en orden), Transporte (canal entre cadenas, por ejemplo HRMP) y Confianza (configuración del executor con IsReserve, IsTeleporter y Barrier). Abajo a la izquierda, tres instrucciones apiladas: WithdrawAsset lleva del origen al Holding, BuyExecution paga el peso con el Holding y DepositAsset lleva del Holding al beneficiario. Abajo a la derecha, dos carriles. En el de reserva, la cadena A pide a la reserva R, que guarda el activo real, y R avisa a la cadena B, que acuña un derivado; B confía en que R guarda y respalda el activo. En el de teletransporte, la cadena A quema el activo y avisa directamente a la cadena B, que crea el mismo activo; B confía en que A lo destruyó.
pallet-xcm expone ambos caminos a los usuarios: limited_reserve_transfer_assets y limited_teleport_assets, entre otras llamadas. [5] Ambas llevan la misma advertencia: si la ejecución remota necesita más peso que weight_limit, "the operation will fail and the sent assets may be at risk." No es un detalle de interfaz: un límite mal calculado puede dejar activos atrapados en el destino.
Qué modelo de transferencia usar
Dónde se declara la confianza: el executor
La confianza no se negocia en cada mensaje. Se fija en la configuración del executor, el tipo que el runtime entrega a XcmExecutor. Tres entradas de xcm-executor/src/config.rs concentran las decisiones de seguridad: [6]
IsReserve: "Combinations of (Asset, Location) pairs which we trust as reserves."IsTeleporter: "Combinations of (Asset, Location) pairs which we trust as teleporters."Barrier: "Whether we should execute the given XCM at all."
Leídas juntas, responden la pregunta del escenario inicial. La parachain del segundo equipo acepta el token de fidelidad solo si su IsReserve incluye el par (token, parachain emisora). Si no lo incluye, ReserveAssetDeposited falla aunque el mensaje esté bien formado. Y antes de eso, la barrera decide si el programa se ejecuta siquiera; un patrón habitual es exigir que el programa pague su ejecución, como hace la barrera AllowTopLevelPaidExecutionFrom de xcm_builder.
El Trader completa el cuadro: define cómo se compra peso con activos, es decir, qué precio cobra tu cadena por ejecutar mensajes ajenos. [6] Un Trader que acepta cualquier activo como pago abre la puerta a programas que consumen cómputo pagando con algo sin valor.
Para quien diseña el runtime, la revisión de seguridad de XCM es la revisión de estos tipos. El formato y el canal son comunes a todo el ecosistema; la política es tuya.
Revisión de un executor antes de abrir un canal
0 de 5 revisados
El canal: lo que XCM no define
Si XCM es el idioma, alguien tiene que llevar la carta. Entre parachains, Polkadot Docs describe el protocolo HRMP (Horizontal Relay-routed Message Passing): una parachain solicita un canal, la otra lo acepta, y el resultado es "a unidirectional HRMP channel, where messages can flow in only one direction between the two parachains." [7] Para comunicarse en los dos sentidos hacen falta dos canales.
Hay un detalle recursivo que ayuda a entender la separación de capas: la propia solicitud del canal se envía como un mensaje XCM a la relay chain, con Transact para invocar hrmpInitOpenChannel. [7] El formato es el mismo; lo que cambia es quién lo recibe y qué llamada autoriza.
Otros transportes (mensajes hacia arriba y hacia abajo entre parachain y relay chain, o el futuro XCMP) no se investigaron en fuentes primarias para este capítulo; sus detalles quedan a validar. Lo que sí es estable es la regla de diseño: cambiar el canal no cambia el significado del programa ni la política del executor.
Para mensajes hacia fuera del ecosistema, Polkadot Docs señala que XCM opera dentro de Polkadot y que los puentes extienden esa función a cadenas externas como Ethereum. [8] Un puente necesita algo que XCM no aporta: una prueba verificable de que el bloque de origen es final. Ese es el tema de BEEFY.
Qué cambia respecto de Ethereum
Quien viene de la ruta de Ethereum conoce dos patrones: llamadas entre contratos dentro de la misma cadena, que son síncronas y atómicas, y puentes entre cadenas, que son asíncronos y dependen de quién verifica qué. XCM se parece al segundo patrón, no al primero.
Comparación
Mensajes entre sistemas: Ethereum frente a XCM
Llamada entre contratos en Ethereum
Misma cadena, mismo estado, una sola transacción.
- Síncrona: el llamador recibe el resultado.
- Atómica: si algo falla, todo revierte.
- Confianza: la del propio consenso de Ethereum.
Puente desde Ethereum
Dos consensos distintos, un contrato verifica mensajes.
- Asíncrono.
- La seguridad depende de quién atestigua el mensaje.
- Formato propio de cada puente.
XCM entre parachains
Consensos separados que comparten relay chain y formato.
- Asíncrono y sin respuesta automática.
- La confianza se declara en el executor del receptor.
- Formato común a todas las cadenas que implementan la XCVM.
La consecuencia más importante para quien llega desde Ethereum es la falta de atomicidad. Un programa XCM que retira en la cadena A y deposita en la cadena B no revierte la primera parte si la segunda falla. Diseñar flujos entre cadenas exige pensar en estados intermedios, reintentos y activos atrapados, igual que en un puente.
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. Ver una transferencia por reserva entre dos parachains locales y reconocer, en un fallo provocado, qué parte del executor lo causó.
Pasos propuestos.
- Extender la red de zombienet del laboratorio de Parachains con Cumulus con una segunda parachain y abrir un canal HRMP en cada sentido.
- Enviar una transferencia de reserva con
pallet-xcmy seguir los eventos en las dos cadenas y en la relay chain. - Quitar a propósito la entrada de la reserva en
IsReservedel runtime receptor, repetir el envío y leer el error que emite el executor.
Evidencia esperada. En el paso 2, un evento de envío en la cadena origen y uno de ejecución completa en la destino, con el saldo del beneficiario aumentado en el importe menos la comisión. En el paso 3, un evento de ejecución fallida en la cadena destino y ningún saldo nuevo para el beneficiario. Los nombres exactos de eventos y errores dependen de la versión del SDK y de XCM, y quedan a validar al construir el laboratorio.
Bibliografía académica
- [1]
Parity Technologies, "polkadot_sdk_docs: XCM," polkadot-sdk, docs/sdk/src/polkadot_sdk/xcm.rs, commit 544e829, 2026.
Definición de XCM, la XCVM, componentes (xcm, xcm-executor, pallet-xcm, xcm-builder) y un programa de transferencia.
- [2]
Polkadot Developers, "Get Started with XCM," polkadot-docs, docs/parachains/interoperability/get-started.md, 2026.
XCM como formato y no protocolo, los cuatro principios y el ejemplo WithdrawAsset, BuyExecution, DepositAsset.
- [3]
Parity Technologies, "xcm: Version 5 of the Cross-Consensus Message format," polkadot-sdk, polkadot/xcm/src/v5/mod.rs, commit 544e829, 2026.
Definición de instrucciones (WithdrawAsset, ReserveAssetDeposited, ReceiveTeleportedAsset, BuyExecution, DepositAsset) y sus notas de seguridad.
- [4]
Parity Technologies, "xcm v5: Location," polkadot-sdk, polkadot/xcm/src/v5/location.rs, commit 544e829, 2026.
Location como ruta relativa: número de padres más junctions; ejemplos de ubicaciones.
- [5]
Parity Technologies, "pallet-xcm," polkadot-sdk, polkadot/xcm/pallet-xcm/src/lib.rs, commit 544e829, 2026.
Llamadas send, execute, limited_reserve_transfer_assets y limited_teleport_assets; advertencia sobre weight_limit.
- [6]
Parity Technologies, "xcm-executor: Config," polkadot-sdk, polkadot/xcm/xcm-executor/src/config.rs, commit 544e829, 2026.
Tipos asociados del executor: IsReserve, IsTeleporter, Barrier, Trader y otros.
- [7]
Polkadot Developers, "Opening HRMP Channels Between Parachains," polkadot-docs, docs/parachains/interoperability/channels-between-parachains.md, 2026.
Apertura de canales HRMP: solicitud, aceptación, canales unidireccionales.
- [8]
Polkadot Developers, "Interoperability," polkadot-docs, docs/reference/parachains/interoperability.md, 2026.
XCM como marco estándar de interacción y puentes hacia redes externas.
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.
Qué es Substrate hoy: el Polkadot SDK por dentro
Substrate ya no es un repositorio aparte: es el framework base del Polkadot SDK. Un mapa de nombres, piezas y crates para empezar sin perderse.
Parachains con Cumulus: seguridad compartida
Cumulus convierte un runtime FRAME en parachain y el nodo en collator; los validadores de la relay chain re-ejecutan cada parablock con su prueba de validez y la finalidad llega desde la relay.
La cadena como función de transición de estado
El modelo mental que sostiene toda la ruta: una función determinista toma el estado y un bloque y devuelve el estado siguiente. En Substrate esa función se llama runtime.
El runtime en Wasm: nodo y runtime hablan por dos puertas
El runtime es un blob Wasm guardado en el estado bajo la clave :code. El nodo lo llama por runtime APIs y el runtime pide ayuda al nodo por host functions. Por qué la segunda puerta casi nunca se ensancha.