fix(runtime): RV12 — el blob no sabia decir quien era y el genesis no construia
Tres defectos encontrados al montar el benchmarking real sobre el WASM. Ninguno era visible desde los tests nativos, y los tres bloqueaban frame-omni-bencher, que es el instrumento que mide los weights de mainnet. 1. LA SECCION runtime_version NO EXISTIA. Faltaba el atributo sp_version::runtime_version sobre VERSION. Esa custom section es la unica via para leer la version del runtime SIN ejecutarlo, que es de lo que depende set_code / forkless upgrade. wasm-builder abortaba con "Couldn't find the runtime_version section". El atributo exige literales, asi que la direccion queda INVERTIDA: VERSION es la fuente unica y las siete constantes publicas se derivan de sus campos. La deriva ya no es cuestion de disciplina, es imposible por construccion (contrafactual verificado: mover el literal pone rojo el test). 2. LOS PRESETS DE GENESIS NO EXISTIAN EN no_std. get_preset y preset_names devolvian None/vacio bajo un cfg(feature = "std") cuyo comentario afirmaba que los presets "solo se consultan en chain_spec generation, no en runtime execution". Falso: en el modelo runtime-driven chain spec el estado se construye DENTRO del WASM. omni-bencher fallaba con "The preset with name development is not available", y chain-spec-builder habria fallado igual. 3. NINGUN PRESET HABIA CONSTRUIDO UN GENESIS VALIDO JAMAS. Los tres poblaban aura.authorities Y session.keys a la vez; con pallet-session cableado, session instala las authorities de Aura via on_genesis_session y el build de Aura revienta con "Authorities are already initialized!". Sobrevivio toda la vida del crate porque todos los tests inspeccionaban el JSON del preset y ninguno llamaba a build_state: se miraba la caja por fuera. Ahora la abre los_tres_presets_construyen_estado (dev-dep sp-io), con contrafactual verificado: repoblar authorities lo pone rojo con el panic exacto. Tambien: el test que fijaba la version llevaba la version en el NOMBRE (runtime_version_v11_did_newtype) y su comentario quedaba mintiendo en cuanto la spec subia. Renombrado a spec_version_vigente_y_transaction_version_intacta. MEDIDO: WASM build exit 0; seccion runtime_version presente y decodificada (spec_name origin-chain, spec_version 12, tx 1); omni-bencher enumera los 19 benchmarks de los 5 pallets custom; 290 tests verde. RV11 -> RV12. TRANSACTION_VERSION intacto. Sin migracion: no hay cadena viva y ninguna transicion de estado cambia. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4bdd0409f9
commit
b7010db328
4 files changed
+143
-55
No files matched your search
Generated
+1
@@ -6555,6 +6555,7 @@ dependencies = [
|
|||||||
"sp-core",
|
"sp-core",
|
||||||
"sp-genesis-builder 0.20.0",
|
"sp-genesis-builder 0.20.0",
|
||||||
"sp-inherents 39.0.0",
|
"sp-inherents 39.0.0",
|
||||||
|
"sp-io 43.0.0",
|
||||||
"sp-offchain 39.0.0",
|
"sp-offchain 39.0.0",
|
||||||
"sp-runtime 44.0.0",
|
"sp-runtime 44.0.0",
|
||||||
"sp-session 41.0.0",
|
"sp-session 41.0.0",
|
||||||
|
|||||||
@@ -106,6 +106,12 @@ log.workspace = true
|
|||||||
# dep rompía isolated WASM build canonical.
|
# dep rompía isolated WASM build canonical.
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
# Solo para `los_tres_presets_construyen_estado`: `TestExternalities` es el unico
|
||||||
|
# sitio donde se puede EJECUTAR `build_state` y descubrir un genesis que panica.
|
||||||
|
# Sin esto los presets se validaban leyendo su JSON, que es mirar la caja por fuera.
|
||||||
|
sp-io = { workspace = true, default-features = true }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
# Slice 2e v0.0.35 — Re-enabled substrate-wasm-builder for active investigation.
|
# Slice 2e v0.0.35 — Re-enabled substrate-wasm-builder for active investigation.
|
||||||
# Slice 2c+2d findings: WASM_BUILD_STD=0 resuelve alloc/exchange_malloc pero
|
# Slice 2c+2d findings: WASM_BUILD_STD=0 resuelve alloc/exchange_malloc pero
|
||||||
|
|||||||
@@ -37,8 +37,6 @@
|
|||||||
//! Los bytes canonical son los **mismos exactos** que `sp_keyring::Sr25519Keyring::Alice.public()`
|
//! Los bytes canonical son los **mismos exactos** que `sp_keyring::Sr25519Keyring::Alice.public()`
|
||||||
//! retorna canonical — verified empíricamente contra Substrate canonical source.
|
//! retorna canonical — verified empíricamente contra Substrate canonical source.
|
||||||
|
|
||||||
#![cfg(feature = "std")]
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
configs::{AuraId, EmissionEcosystemPalletId, GovernanceTreasuryPalletId, GrandpaId},
|
configs::{AuraId, EmissionEcosystemPalletId, GovernanceTreasuryPalletId, GrandpaId},
|
||||||
opaque::SessionKeys,
|
opaque::SessionKeys,
|
||||||
@@ -241,14 +239,22 @@ fn build_genesis(
|
|||||||
fees: FeesConfig {
|
fees: FeesConfig {
|
||||||
initial_profiles: initial_fee_profiles,
|
initial_profiles: initial_fee_profiles,
|
||||||
},
|
},
|
||||||
|
// VACIOS A PROPOSITO — con `pallet-session` (Index 6) cableado, las
|
||||||
|
// authorities de Aura y Grandpa las instala la SESSION, no el genesis
|
||||||
|
// de cada pallet. `initialize_authorities` corta con
|
||||||
|
// `assert!(Authorities::get().is_empty(), "Authorities are already
|
||||||
|
// initialized!")` en cuanto la lista NO esta vacia, y `SessionConfig`
|
||||||
|
// ya la habia puesto: poblar los tres es un panic garantizado en
|
||||||
|
// `build_state`. Se descubrio el 2026-09-09 al correr `omni-bencher`,
|
||||||
|
// que construye el estado de verdad; ningun test lo hacia, asi que los
|
||||||
|
// TRES presets llevaban desde su nacimiento sin construir un genesis
|
||||||
|
// valido ni una sola vez. El test `los_tres_presets_construyen_estado`
|
||||||
|
// existe para que eso no pueda repetirse.
|
||||||
aura: AuraConfig {
|
aura: AuraConfig {
|
||||||
authorities: validators.iter().map(|(_, aura, _)| aura.clone()).collect(),
|
authorities: vec![],
|
||||||
},
|
},
|
||||||
grandpa: GrandpaConfig {
|
grandpa: GrandpaConfig {
|
||||||
authorities: validators
|
authorities: vec![],
|
||||||
.iter()
|
|
||||||
.map(|(_, _, grandpa)| (grandpa.clone(), 1))
|
|
||||||
.collect(),
|
|
||||||
_config: core::marker::PhantomData,
|
_config: core::marker::PhantomData,
|
||||||
},
|
},
|
||||||
session: SessionConfig {
|
session: SessionConfig {
|
||||||
@@ -461,6 +467,33 @@ pub fn preset_names() -> Vec<PresetId> {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
/// LOS TRES PRESETS TIENEN QUE CONSTRUIR ESTADO DE VERDAD, no solo serializar.
|
||||||
|
///
|
||||||
|
/// Este test nace de un fallo que sobrevivio a toda la vida del crate: los
|
||||||
|
/// tres presets poblaban `aura.authorities` Y `session.keys` a la vez, y
|
||||||
|
/// `pallet_session::GenesisConfig::build` instala las authorities de Aura
|
||||||
|
/// via `on_genesis_session`, con lo que el `build` de Aura reventaba con
|
||||||
|
/// «Authorities are already initialized!». Ningun test lo veia porque todos
|
||||||
|
/// inspeccionaban el JSON del preset — la caja por fuera — y `build_state`
|
||||||
|
/// no se ejecutaba en ninguna parte. Lo destapo `frame-omni-bencher`, que
|
||||||
|
/// construye el estado porque no le queda mas remedio.
|
||||||
|
///
|
||||||
|
/// Un preset que serializa pero no construye es un genesis que no existe.
|
||||||
|
#[test]
|
||||||
|
fn los_tres_presets_construyen_estado() {
|
||||||
|
for id in preset_names() {
|
||||||
|
let json = get_preset(&id)
|
||||||
|
.unwrap_or_else(|| panic!("preset {id:?} sin JSON"));
|
||||||
|
let mut ext = sp_io::TestExternalities::new_empty();
|
||||||
|
ext.execute_with(|| {
|
||||||
|
frame_support::genesis_builder_helper::build_state::<RuntimeGenesisConfig>(
|
||||||
|
json.clone(),
|
||||||
|
)
|
||||||
|
.unwrap_or_else(|e| panic!("preset {id:?} no construye estado: {e}"));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn bm_v2_allocations_sum_canonical_to_one_billion_ogc() {
|
fn bm_v2_allocations_sum_canonical_to_one_billion_ogc() {
|
||||||
let total = ECOSYSTEM_ALLOCATION
|
let total = ECOSYSTEM_ALLOCATION
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ use alloc::vec::Vec;
|
|||||||
pub mod configs;
|
pub mod configs;
|
||||||
/// FIX-6 Stage 2b NPoS — pallet_staking config (infra dormida).
|
/// FIX-6 Stage 2b NPoS — pallet_staking config (infra dormida).
|
||||||
pub mod staking;
|
pub mod staking;
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub mod genesis_config_presets;
|
pub mod genesis_config_presets;
|
||||||
pub mod opaque;
|
pub mod opaque;
|
||||||
|
|
||||||
@@ -214,13 +213,27 @@ pub type TxExtension = (
|
|||||||
// Runtime metadata canonical (SPEC_NAME + version constants)
|
// Runtime metadata canonical (SPEC_NAME + version constants)
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
|
/// Extrae el `&'static str` de un `Cow::Borrowed` en contexto `const`.
|
||||||
|
///
|
||||||
|
/// Existe para que `SPEC_NAME`/`IMPL_NAME` se DERIVEN de [`VERSION`] en vez de
|
||||||
|
/// repetir el literal: el atributo `#[sp_version::runtime_version]` obliga a que
|
||||||
|
/// los campos de `VERSION` sean literales (ver la nota sobre esa const), y una
|
||||||
|
/// segunda copia del literal es una divergencia esperando a ocurrir. `panic!` en
|
||||||
|
/// `const fn` se evalua en compilacion: un `Cow::Owned` seria error de build.
|
||||||
|
const fn borrowed_str(cow: &'static alloc::borrow::Cow<'static, str>) -> &'static str {
|
||||||
|
match cow {
|
||||||
|
alloc::borrow::Cow::Borrowed(s) => s,
|
||||||
|
alloc::borrow::Cow::Owned(_) => panic!("VERSION debe usar Cow::Borrowed"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Canonical spec name per Substrate genesis canonical. Identifica el chain
|
/// Canonical spec name per Substrate genesis canonical. Identifica el chain
|
||||||
/// runtime canonical en bloques + storage proofs.
|
/// runtime canonical en bloques + storage proofs.
|
||||||
pub const SPEC_NAME: &str = "origin-chain";
|
pub const SPEC_NAME: &str = borrowed_str(&VERSION.spec_name);
|
||||||
|
|
||||||
/// Canonical implementation name canonical. Distingue diferentes node binaries
|
/// Canonical implementation name canonical. Distingue diferentes node binaries
|
||||||
/// que ejecutan el mismo spec (canonical: "origin-chain-charon").
|
/// que ejecutan el mismo spec (canonical: "origin-chain-charon").
|
||||||
pub const IMPL_NAME: &str = "origin-chain-charon";
|
pub const IMPL_NAME: &str = borrowed_str(&VERSION.impl_name);
|
||||||
|
|
||||||
/// Canonical runtime version canonical. Bumped cada forkless upgrade via
|
/// Canonical runtime version canonical. Bumped cada forkless upgrade via
|
||||||
/// `set_code` extrinsic governance canonical.
|
/// `set_code` extrinsic governance canonical.
|
||||||
@@ -284,19 +297,37 @@ pub const IMPL_NAME: &str = "origin-chain-charon";
|
|||||||
/// `DidToAccount` no requiere migración. El bump es por **higiene de metadata**:
|
/// `DidToAccount` no requiere migración. El bump es por **higiene de metadata**:
|
||||||
/// el `TypeInfo` de la clave de storage pasa a nombrarse `Did`, y los clientes
|
/// el `TypeInfo` de la clave de storage pasa a nombrarse `Did`, y los clientes
|
||||||
/// que cachean metadata deben re-leerla. TRANSACTION_VERSION intacto.
|
/// que cachean metadata deben re-leerla. TRANSACTION_VERSION intacto.
|
||||||
pub const RUNTIME_VERSION: u32 = 11;
|
///
|
||||||
|
/// **v12 (el blob por fin se declara, y el genesis por fin construye)**: tres
|
||||||
|
/// defectos encontrados al montar el benchmarking real sobre el WASM, ninguno
|
||||||
|
/// visible desde los tests nativos. (a) El blob **no emitia la custom section
|
||||||
|
/// `runtime_version`** — faltaba `#[sp_version::runtime_version]` sobre `VERSION`.
|
||||||
|
/// Esa seccion es la unica via para leer la version del runtime SIN ejecutarlo,
|
||||||
|
/// que es de lo que depende `set_code` / forkless upgrade: el blob no sabia decir
|
||||||
|
/// quien era. (b) `GenesisBuilder::get_preset`/`preset_names` devolvian `None`/
|
||||||
|
/// vacio bajo `no_std` por un `#[cfg(feature = "std")]` cuyo comentario afirmaba
|
||||||
|
/// que los presets «solo se consultan en chain_spec generation» — falso en el
|
||||||
|
/// modelo runtime-driven chain spec, donde el estado se construye DENTRO del
|
||||||
|
/// WASM. (c) Los tres presets poblaban `aura.authorities` **y** `session.keys`
|
||||||
|
/// a la vez, y con `pallet-session` cableado eso es un panic garantizado
|
||||||
|
/// («Authorities are already initialized!»): **ningun preset habia construido
|
||||||
|
/// un genesis valido jamas**, porque ningun test llamaba a `build_state`. Ahora
|
||||||
|
/// lo llama `los_tres_presets_construyen_estado`, con contrafactual verificado.
|
||||||
|
/// Nada de esto cambia una transicion de estado de la cadena viva (no hay cadena
|
||||||
|
/// viva): el bump es por higiene de blob y de metadata. TRANSACTION_VERSION intacto.
|
||||||
|
pub const RUNTIME_VERSION: u32 = VERSION.spec_version;
|
||||||
|
|
||||||
/// Canonical authoring version per Substrate semver canonical.
|
/// Canonical authoring version per Substrate semver canonical.
|
||||||
pub const AUTHORING_VERSION: u32 = 1;
|
pub const AUTHORING_VERSION: u32 = VERSION.authoring_version;
|
||||||
|
|
||||||
/// Canonical impl version per Substrate semver canonical.
|
/// Canonical impl version per Substrate semver canonical.
|
||||||
pub const IMPL_VERSION: u32 = 1;
|
pub const IMPL_VERSION: u32 = VERSION.impl_version;
|
||||||
|
|
||||||
/// Canonical transaction version per Substrate semver canonical.
|
/// Canonical transaction version per Substrate semver canonical.
|
||||||
pub const TRANSACTION_VERSION: u32 = 1;
|
pub const TRANSACTION_VERSION: u32 = VERSION.transaction_version;
|
||||||
|
|
||||||
/// Canonical state version: v1 per Substrate stable2509+ canonical.
|
/// Canonical state version: v1 per Substrate stable2509+ canonical.
|
||||||
pub const STATE_VERSION: u8 = 1;
|
pub const STATE_VERSION: u8 = VERSION.system_version;
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Runtime composition canonical (frame_support::runtime macro)
|
// Runtime composition canonical (frame_support::runtime macro)
|
||||||
@@ -641,35 +672,26 @@ impl_runtime_apis! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
|
fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
|
||||||
// Canonical Phase 1.7: 3 presets disponibles canonical (development +
|
// Canonical Phase 1.7: 3 presets (development + local_testnet +
|
||||||
// local_testnet + mainnet_genesis). Cuando feature `std` activo
|
// mainnet_genesis), servidos TAMBIEN en no_std.
|
||||||
// (chain_spec generation time), delegamos canonical al
|
//
|
||||||
// `genesis_config_presets::get_preset`. En no_std (WASM runtime),
|
// Historia, porque el comentario anterior documentaba una suposicion
|
||||||
// siempre return None canonical — los presets canonical solo se
|
// FALSA y costo un bloqueo: decia que los presets «solo se consultan
|
||||||
// consultan en chain_spec generation, no en runtime execution.
|
// en chain_spec generation, no en runtime execution» y devolvia None
|
||||||
#[cfg(feature = "std")]
|
// bajo no_std. Eso rompe el modelo runtime-driven chain spec entero:
|
||||||
{
|
// `frame-omni-bencher` construye el estado de genesis llamando a este
|
||||||
frame_support::genesis_builder_helper::get_preset::<RuntimeGenesisConfig>(
|
// metodo DENTRO del WASM, y `chain-spec-builder` genera el spec a
|
||||||
id,
|
// partir del blob solo. Con el gate puesto, ambos fallaban con «The
|
||||||
genesis_config_presets::get_preset,
|
// preset with name Some("development") is not available» — medido
|
||||||
)
|
// 2026-09-09 al montar el benchmarking real.
|
||||||
}
|
frame_support::genesis_builder_helper::get_preset::<RuntimeGenesisConfig>(
|
||||||
#[cfg(not(feature = "std"))]
|
id,
|
||||||
{
|
genesis_config_presets::get_preset,
|
||||||
let _ = id;
|
)
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
|
fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
|
||||||
#[cfg(feature = "std")]
|
genesis_config_presets::preset_names()
|
||||||
{
|
|
||||||
genesis_config_presets::preset_names()
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "std"))]
|
|
||||||
{
|
|
||||||
Vec::new()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -915,15 +937,35 @@ mod benches {
|
|||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
/// Canonical `RuntimeVersion` per Substrate canonical. Consumed by `sp_api::Core::version()`.
|
/// Canonical `RuntimeVersion` per Substrate canonical. Consumed by `sp_api::Core::version()`.
|
||||||
|
///
|
||||||
|
/// # Por que los valores son literales y no las constantes con nombre
|
||||||
|
///
|
||||||
|
/// `#[sp_version::runtime_version]` emite la **custom section `runtime_version`**
|
||||||
|
/// del blob WASM: la unica forma que tiene un nodo de leer la version del runtime
|
||||||
|
/// SIN ejecutarlo (imprescindible para `set_code` / forkless upgrade). Su parser
|
||||||
|
/// (`sp-version-proc-macro`, `ParseRuntimeVersion`) solo acepta literales en
|
||||||
|
/// `spec_name`, `impl_name` y los cuatro `u32`/`u8`; una constante con nombre da
|
||||||
|
/// «only numeric literals are supported here». Sin el atributo, `wasm-builder`
|
||||||
|
/// aborta con «Couldn't find the `runtime_version` section».
|
||||||
|
///
|
||||||
|
/// Para que el literal no pueda divergir de la constante publica, la direccion
|
||||||
|
/// esta INVERTIDA respecto de lo habitual: esta const es la fuente unica de
|
||||||
|
/// verdad y `SPEC_NAME`, `RUNTIME_VERSION`, `AUTHORING_VERSION`, `IMPL_VERSION`,
|
||||||
|
/// `TRANSACTION_VERSION` y `STATE_VERSION` se derivan de sus campos. Bumpear una
|
||||||
|
/// version se hace AQUI, en un unico sitio.
|
||||||
|
///
|
||||||
|
/// `apis` lo ignora el macro a proposito: la seccion de runtime APIs la emite
|
||||||
|
/// `impl_runtime_apis!` por su cuenta.
|
||||||
|
#[sp_version::runtime_version]
|
||||||
pub const VERSION: sp_version::RuntimeVersion = sp_version::RuntimeVersion {
|
pub const VERSION: sp_version::RuntimeVersion = sp_version::RuntimeVersion {
|
||||||
spec_name: alloc::borrow::Cow::Borrowed(SPEC_NAME),
|
spec_name: alloc::borrow::Cow::Borrowed("origin-chain"),
|
||||||
impl_name: alloc::borrow::Cow::Borrowed(IMPL_NAME),
|
impl_name: alloc::borrow::Cow::Borrowed("origin-chain-charon"),
|
||||||
authoring_version: AUTHORING_VERSION,
|
authoring_version: 1,
|
||||||
spec_version: RUNTIME_VERSION,
|
spec_version: 12,
|
||||||
impl_version: IMPL_VERSION,
|
impl_version: 1,
|
||||||
apis: RUNTIME_API_VERSIONS,
|
apis: RUNTIME_API_VERSIONS,
|
||||||
transaction_version: TRANSACTION_VERSION,
|
transaction_version: 1,
|
||||||
system_version: STATE_VERSION,
|
system_version: 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Canonical Executive type canonical (FRAME executive wrapper).
|
/// Canonical Executive type canonical (FRAME executive wrapper).
|
||||||
@@ -942,14 +984,20 @@ use sp_api::impl_runtime_apis;
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
/// Fija la version vigente y la invariante que la acompaña.
|
||||||
|
///
|
||||||
|
/// El test NO cuenta la historia de cada version — eso vive en el doc comment
|
||||||
|
/// de [`RUNTIME_VERSION`], que es donde se lee. Aqui solo se pinchan dos cosas:
|
||||||
|
/// que subir la spec es un acto deliberado (este assert se rompe y hay que
|
||||||
|
/// venir a tocarlo), y que `TRANSACTION_VERSION` sigue en 1 — un bump suyo
|
||||||
|
/// invalida cada extrinsic firmada en vuelo, y jamas puede colarse de rebote.
|
||||||
|
///
|
||||||
|
/// El nombre anterior clavaba una version concreta en el identificador
|
||||||
|
/// (`runtime_version_v11_did_newtype`) y su comentario quedo mintiendo en el
|
||||||
|
/// mismo commit en que la version subio a 12.
|
||||||
#[test]
|
#[test]
|
||||||
fn runtime_version_v11_did_newtype() {
|
fn spec_version_vigente_y_transaction_version_intacta() {
|
||||||
// v11 = condición #3 de Mathi: `Did` pasa de alias de `AssetHash` a newtype
|
assert_eq!(RUNTIME_VERSION, 12);
|
||||||
// propio (cierra la confusión cross-namespace que el contexto KDF compartido
|
|
||||||
// agravaba). NO cambia la transición de estado — mismos bytes, mismo encoding
|
|
||||||
// SCALE ⇒ sin migración; el bump es higiene de metadata (TypeInfo).
|
|
||||||
// (v10 = identidad unificada `origin/identity/v1`; v9 = weights DB-aware.)
|
|
||||||
assert_eq!(RUNTIME_VERSION, 11);
|
|
||||||
assert_eq!(TRANSACTION_VERSION, 1);
|
assert_eq!(TRANSACTION_VERSION, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user