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>
61 lines
2.4 KiB
Python
61 lines
2.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Parche TEMPORAL para el simulacro de set_code: el runtime siguiente (spec N+1) con una migración marcada.
|
|
|
|
python3 scripts/e2e/parche_simulacro.py aplicar # spec N → N+1 + SimulacroSetCode
|
|
(construir el WASM: cargo build -p origin-chain-runtime --features wasm-build)
|
|
(copiar target/debug/wbuild/origin-chain-runtime/origin_chain_runtime.wasm fuera)
|
|
python3 scripts/e2e/parche_simulacro.py restaurar # deja lib.rs byte a byte como estaba
|
|
|
|
La migración escribe `:origin:simulacro_set_code` = N+1 (u32 LE). Si esa marca aparece después
|
|
del upgrade, `on_runtime_upgrade` corrió. NUNCA se commitea: `restaurar` lo comprueba con
|
|
un hash.
|
|
"""
|
|
import hashlib, pathlib, re, shutil, sys
|
|
|
|
LIB = pathlib.Path(__file__).resolve().parents[2] / "crates/origin-chain-runtime/src/lib.rs"
|
|
COPIA = LIB.with_suffix(".rs.simulacro-orig")
|
|
|
|
|
|
def sha(p):
|
|
return hashlib.sha256(p.read_bytes()).hexdigest()
|
|
|
|
|
|
def aplicar():
|
|
if COPIA.exists():
|
|
sys.exit(f"ya hay un parche aplicado ({COPIA}); restaura primero")
|
|
s = LIB.read_text()
|
|
m = re.search(r" spec_version: (\d+),", s)
|
|
n = int(m.group(1)) + 1
|
|
exe = " AllPalletsWithSystem,\n (),\n>;"
|
|
if s.count(exe) != 1:
|
|
sys.exit("el Executive ya tiene migraciones: este parche no sabe combinarlas")
|
|
shutil.copy2(LIB, COPIA)
|
|
s = s.replace(m.group(0), f" spec_version: {n},", 1)
|
|
s = s.replace(exe, f""" AllPalletsWithSystem,
|
|
SimulacroSetCode,
|
|
>;
|
|
|
|
/// SIMULACRO (no se commitea): deja una marca para probar que la migración corrió.
|
|
pub struct SimulacroSetCode;
|
|
impl frame_support::traits::OnRuntimeUpgrade for SimulacroSetCode {{
|
|
fn on_runtime_upgrade() -> frame_support::weights::Weight {{
|
|
frame_support::storage::unhashed::put(b":origin:simulacro_set_code", &{n}u32);
|
|
frame_support::weights::Weight::from_parts(1_000_000, 0)
|
|
}}
|
|
}}""", 1)
|
|
LIB.write_text(s)
|
|
print(f"aplicado: spec {n - 1} → {n} + SimulacroSetCode (original en {COPIA.name}, sha {sha(COPIA)[:12]})")
|
|
|
|
|
|
def restaurar():
|
|
if not COPIA.exists():
|
|
sys.exit("no hay parche que restaurar")
|
|
esperado = sha(COPIA)
|
|
shutil.copy2(COPIA, LIB)
|
|
assert sha(LIB) == esperado, "lib.rs no quedó idéntico al original"
|
|
COPIA.unlink()
|
|
print(f"restaurado: lib.rs idéntico al original (sha {esperado[:12]})")
|
|
|
|
|
|
{"aplicar": aplicar, "restaurar": restaurar}.get(sys.argv[1] if len(sys.argv) > 1 else "", lambda: sys.exit(__doc__))()
|