feat(node): Origin Chain produce su primer bloque — el bloqueo arquitectural era un diagnostico falso

El node nunca habia producido un bloque: service.rs y rpc.rs estaban fuera del
build desde v0.0.49 por un «bloqueo arquitectural» que afirmaba que las crates
publicadas sc-consensus-aura 0.52.0 y sp-consensus-aura 0.45.0 no tenian
standalone::slot_duration_at ni from_timestamp_and_slot_duration. Las dos estan
ahi, en crates.io. La nota guio la decision durante meses.

Causa real, medida con cargo check (362 errores) y cargo tree: el workspace
mezclaba dos releases de polkadot-sdk. Las sc-* del cliente arrastraban
sp-runtime 43 y las frame-* del runtime sp-runtime 44: 36 crates del nucleo
duplicadas y errores de la forma «Block no satisface Block». Cura: alinear diez
versiones del Cargo.toml (sc-cli 0.55, sc-service 0.54, sc-network 0.53,
sc-consensus 0.52, sc-consensus-aura 0.53, sc-consensus-grandpa 0.38,
sc-offchain 48, sp-blockchain 42, substrate-frame-rpc-system 47,
sc-telemetry 30.0.1). El lock solo PIERDE la generacion vieja (1210 -> 1123
entradas); ninguna crate que use el runtime cambia de version.

rpc.rs: el client pasa a ser el FullClient concreto. Nuestro node trabaja sobre
el Block completo del runtime, que lleva dentro ChainAccountId, una proyeccion
(<<MultiSignature as Verify>::Signer as IdentifyAccount>::AccountId) que rustc
no normaliza dentro de un where-clause generico: 6 errores de «un bound
declarado en la firma no se satisface». Con el generico fallaba, con el
concreto compila.

main.rs: subcomando run (sc_cli::RunCmd), que arranca new_full con litep2p o
libp2p. chain_spec.rs: node_chain_spec construye un GenericChainSpec con el
WASM real del runtime (build-spec sigue con su JSON). run --chain mainnet se
RECHAZA: sus validadores son placeholder sin llave (gate L-3) y un node con ese
genesis no produciria nunca, en silencio. Test con contrafactual: sin el brazo
mainnet el id cae en la rama de ruta y falla como «fichero no encontrado»; el
test exige la razon, y en rojo lo dijo asi.

Medido (build con --features wasm-build, run --dev --tmp):
- bloque #1 importado 2026-09-23 20:04:30, uno cada ~6 s (Aura);
- GRANDPA finaliza: #7 finalizado con best #9 a los 60 s;
- RPC: chain_getHeader, chain_getFinalizedHead, system_accountNextIndex
  (Alice = 0) y system_properties (OGC, 18 decimales, ss58 42) responden;
- «Essential task txpool-background failed» aparece SOLO al SIGINT
  (0 ocurrencias a los 50 s con RPC servido; 1 al segundo del SIGINT).
- cargo test --workspace: 318 passed, 0 failed (igual que RV14) + 1 nuevo.

macOS 27: el build necesita DEVELOPER_DIR=/Library/Developer/CommandLineTools
mientras la licencia de Xcode 27 no este aceptada (exit 69 en cc y git).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
CharonandClaude Opus 5.5 committed 2026-09-23 20:09:25 -05:00
1 parent defd3fa580
commit 63918f365b
6 files changed
+681 -1696

No files matched your search

+24 -8
View File
@@ -66,7 +66,9 @@ pub fn new_partial(config: &Configuration) -> Result<Service, ServiceError> {
let client = Arc::new(client);
let telemetry = telemetry.map(|(worker, telemetry)| {
task_manager.spawn_handle().spawn("telemetry", None, worker.run());
task_manager
.spawn_handle()
.spawn("telemetry", None, worker.run());
telemetry
});
@@ -92,8 +94,8 @@ pub fn new_partial(config: &Configuration) -> Result<Service, ServiceError> {
)?;
let cidp_client = client.clone();
let import_queue =
sc_consensus_aura::import_queue::<AuraPair, _, _, _, _, _>(ImportQueueParams {
let import_queue = sc_consensus_aura::import_queue::<AuraPair, _, _, _, _, _>(
ImportQueueParams {
block_import: grandpa_block_import.clone(),
justification_import: Some(Box::new(grandpa_block_import.clone())),
client: client.clone(),
@@ -120,7 +122,8 @@ pub fn new_partial(config: &Configuration) -> Result<Service, ServiceError> {
check_for_equivocation: Default::default(),
telemetry: telemetry.as_ref().map(|x| x.handle()),
compatibility_mode: Default::default(),
})?;
},
)?;
Ok(sc_service::PartialComponents {
client,
@@ -160,7 +163,11 @@ pub fn new_full<
let peer_store_handle = net_config.peer_store_handle();
let grandpa_protocol_name = sc_consensus_grandpa::protocol_standard_name(
&client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"),
&client
.block_hash(0)
.ok()
.flatten()
.expect("Genesis block exists; qed"),
&config.chain_spec,
);
let (grandpa_protocol_config, grandpa_notification_service) =
@@ -208,7 +215,9 @@ pub fn new_full<
task_manager.spawn_handle().spawn(
"offchain-workers-runner",
"offchain-worker",
offchain_workers.run(client.clone(), task_manager.spawn_handle()).boxed(),
offchain_workers
.run(client.clone(), task_manager.spawn_handle())
.boxed(),
);
}
@@ -224,7 +233,10 @@ pub fn new_full<
let pool = transaction_pool.clone();
Box::new(move |_| {
let deps = crate::rpc::FullDeps { client: client.clone(), pool: pool.clone() };
let deps = crate::rpc::FullDeps {
client: client.clone(),
pool: pool.clone(),
};
crate::rpc::create_full(deps).map_err(Into::into)
})
};
@@ -293,7 +305,11 @@ pub fn new_full<
if enable_grandpa {
// Si el node no participa activamente en consensus, no necesita keystore.
let keystore = if role.is_authority() { Some(keystore_container.keystore()) } else { None };
let keystore = if role.is_authority() {
Some(keystore_container.keystore())
} else {
None
};
let grandpa_config = sc_consensus_grandpa::Config {
gossip_duration: Duration::from_millis(333),