Ensayo en vivo el 2026-10-12, nodo --dev con WASM real, todo firmado por RPC como un wallet:
- A, control negativo: set_code con la MISMA spec 16 → Sudid Err(System, 1) =
SpecVersionNeedsToIncrease.
- B, el upgrade: sudo(set_code) con spec 17 → CodeUpdated + Sudid Ok.
- El RPC anuncia 17 y LastRuntimeUpgrade pasa de {16,"origin-chain"} a {17,"origin-chain"}.
- La migración del simulacro dejó su marca (0x11000000): on_runtime_upgrade corrió.
- C, un wallet tras el upgrade: firmado con spec 16 → «bad signature»; con spec 17 →
ExtrinsicSuccess.
- La finalidad siguió: el bloque del upgrade (#5) quedó finalizado.
Contrafactual, nodo sin type Version (el runtime de antes de 11e532e):
- LastRuntimeUpgrade = {0, ""}.
- Firmando como wallet → «bad signature».
- Firmando con spec 0 para poder llegar → Sudid Err(System, 0) = InvalidSpecName.
- Ningún upgrade y ninguna marca.
O sea: hasta el 7-oct la cadena no podía cambiar su runtime sin un fork.
Herramientas, para repetirlo antes de la testnet:
- scripts/e2e/simulacro_set_code.py: los pasos A, B y C contra un nodo vivo. Lo corrí tal cual
y reproduce lo de arriba.
- scripts/e2e/parche_simulacro.py: aplica de forma temporal la spec N+1 con la migración
marcada, y al restaurar comprueba por hash que lib.rs queda idéntico.
- firmar_como_wallet:
- modo set_code:<ruta> (sudo de //Alice);
- spec y tx opcionales: tras un upgrade, el wallet firma con la versión que anuncia el RPC;
- hex completo: HexDisplay recortaba con «...» pasados 1024 bytes.
Las builds son reproducibles: los dos WASM salieron con el mismo sha en dos builds separados
(9b933ff1 spec 16, 51663085 spec 17).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>