feat(slice-4): v0.0.49 — core2 yanked unblock + sc-service WIP (crates.io API gap found)
Slice 4 Ship 2 parcial. RESUELVE el blocker real que difirió sc-service 3
sesiones (core2 yanked), pero DESCUBRE un segundo bloqueo arquitectural que
requiere decisión de David. Build verde, 213 tests, sin regresiones.
=== RESUELTO: core2 yanked (el muro de 3 sesiones) ===
sc-network-types 0.16 → cid ^0.9 (0.9.0 yanked) → core2 ^0.4 (0.4.0 yanked,
las no-yanked son 0.3.x que no satisfacen ^0.4). Cargo no auto-selecciona
versiones yanked → resolución fallaba. Era exactamente lo documentado en
chain_spec.rs Slice 3 que difirió sc-service.
Fix: vendorizado el .crate publicado de core2 0.4.0 (yanked pero descargable)
en vendor/core2-0.4.0/ + [patch.crates-io] core2 = { path = ... }. Una path
source es seleccionable independiente del estado yanked. El git source
(technocreatives/core2 master) resultó ser workspace ≤0.3.x, no servía.
=== DESCUBIERTO: crates.io consensus crates ≠ git tag API ===
Las crates sc-/sp- consensus PUBLICADAS (sc-consensus-aura 0.52.0 +
sp-consensus-aura 0.45.0) tienen API DISTINTA al git tag polkadot-stable2509-3
bajo el MISMO número de versión:
- git tag: sc_consensus_aura::standalone::slot_duration_at +
sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration
- crates.io: slot_duration_at en root + NO existe slot InherentDataProvider
(Slot no implementa el trait; Slot::from_timestamp toma 1 arg)
polkadot-sdk reusa números de versión con cambios git no publicados.
Construir un node service real requiere migrar TODO el stack sc-/sp- consensus
a git sources del tag — la misma cirugía duplicate-crate que golpeó pallet-revive
(Ship 2 v0.0.39). Decisión arquitectural para David.
Cambios:
- Cargo.toml: [patch.crates-io] core2 path vendor + sp-timestamp 39 + sp-blockchain 41
- vendor/core2-0.4.0/: crate vendorizado (yanked artifact original)
- node Cargo.toml: 13 sc-* + sp- consensus deps + jsonrpsee/rpc + core2 unblock dep
- node src/service.rs + rpc.rs: WIP escritos (verbatim stable2509-3 + 2 fixes API
crates.io), NO mod-declarados (preservados para siguiente fase)
- node src/main.rs: finding documentado, mods service/rpc neutralizados
Verificación:
- cargo check -p origin-chain-node: EXIT 0 (deps resuelven vía core2, mods off)
- cargo test --workspace: 213 verde, 0 fail, sin regresiones
- core2 0.4.0 + cid 0.9.0 ahora en Cargo.lock (vía path patch)
Próximo: decisión David — (A) migrar sc-/sp- consensus a git sources tag
stable2509-3 (real node, riesgo duplicate-crate) vs (B) mantener publicadas
(node service diferido a futura generación Substrate). Ver SLICE_4 plan §10.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
05b6c70fca
commit
e0e0b907b7
24 files changed
+12242
-227
No files matched your search
@@ -7,19 +7,69 @@ license.workspace = true
|
||||
authors.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
description = "Origin Chain node binary canonical. Phase 1.6+ Slice 1 (v0.0.10): CLI skeleton + preset listing. Slice 3 (v0.0.13): real sc_chain_spec::GenericChainSpec builder canonical via mock-WASM fallback. Real sc-service builder + JSON-RPC + WASM binary canonical land Slices 2c + 4."
|
||||
description = "Origin Chain node binary. Phase 1.6+ Slice 4 (v0.0.49+): full sc-service builder (Aura + Grandpa consensus + JSON-RPC + libp2p networking + telemetry) + sc_service::GenericChainSpec con WASM_BINARY real. Pilar 4 settlement layer."
|
||||
|
||||
[[bin]]
|
||||
name = "origin-chain-node"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
origin-chain-runtime.workspace = true
|
||||
sp-genesis-builder.workspace = true
|
||||
# Slice 3 canonical (v0.0.13) — own minimal ChainSpec JSON builder canonical via
|
||||
# serde_json puro. sc-chain-spec dep canonical evitada (43/44.0.0 trae sc-network
|
||||
# 0.50/0.51 mismatch + cid 0.9.0 yanked core2). Real sc_chain_spec::GenericChainSpec
|
||||
# canonical land en Slice 4 post workspace sc-* upgrade canonical sin yanked deps.
|
||||
# Runtime (std host-side). El feature `wasm-build` (opt-in, ver [features]) se
|
||||
# propaga al runtime para poblar WASM_BINARY consumido por chain_spec.
|
||||
origin-chain-runtime = { workspace = true, features = ["std"] }
|
||||
|
||||
# ── Substrate client (sc-service stack, stable2509-3) ──────────
|
||||
sc-cli.workspace = true
|
||||
sc-service.workspace = true
|
||||
sc-executor.workspace = true
|
||||
sc-network.workspace = true
|
||||
sc-consensus.workspace = true
|
||||
sc-consensus-aura.workspace = true
|
||||
sc-consensus-grandpa.workspace = true
|
||||
sc-transaction-pool.workspace = true
|
||||
sc-transaction-pool-api.workspace = true
|
||||
sc-client-api.workspace = true
|
||||
sc-basic-authorship.workspace = true
|
||||
sc-telemetry.workspace = true
|
||||
sc-offchain.workspace = true
|
||||
|
||||
# ── Substrate primitives (host-side, std) ─────────────────────
|
||||
sp-core = { workspace = true, features = ["std"] }
|
||||
sp-runtime = { workspace = true, features = ["std"] }
|
||||
sp-io = { workspace = true, features = ["std"] }
|
||||
sp-timestamp = { workspace = true, features = ["std"] }
|
||||
sp-consensus-aura = { workspace = true, features = ["std"] }
|
||||
sp-api = { workspace = true, features = ["std"] }
|
||||
sp-block-builder = { workspace = true, features = ["std"] }
|
||||
sp-genesis-builder = { workspace = true, features = ["std"] }
|
||||
sp-blockchain.workspace = true
|
||||
|
||||
# ── RPC server (jsonrpsee) ────────────────────────────────────
|
||||
jsonrpsee.workspace = true
|
||||
substrate-frame-rpc-system.workspace = true
|
||||
pallet-transaction-payment-rpc.workspace = true
|
||||
|
||||
# ── CLI + async + utils ───────────────────────────────────────
|
||||
clap = { workspace = true }
|
||||
futures.workspace = true
|
||||
serde_json.workspace = true
|
||||
log.workspace = true
|
||||
|
||||
# ── Yanked-version unblock (Slice 4 stable2509-3 ecosystem wart) ──
|
||||
# `sc-network-types 0.16.0` depende de `cid ^0.9`, y `cid 0.9.0` (única 0.9.x,
|
||||
# yanked) requiere `core2 ^0.4` — y `core2 0.4.0` también está yanked (las
|
||||
# no-yanked son 0.3.x, que NO satisfacen ^0.4). La resolución falla porque cargo
|
||||
# no auto-selecciona versiones yanked. El pin exacto `=` SÍ permite versiones
|
||||
# yanked, forzando 0.4.0 al grafo para satisfacer la dependencia transitiva de
|
||||
# cid. Dep no usada en código — solo desbloquea el resolver. Era el blocker real
|
||||
# que difirió sc-service en Slice 3 (documentado en chain_spec.rs).
|
||||
core2 = { version = "=0.4.0", default-features = false }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
# Slice 4: activa la generación del WASM_BINARY real (runtime build vía
|
||||
# substrate-wasm-builder). Requiere env vars CC=LLVM (ver SLICE_2E). Sin este
|
||||
# feature el node compila host-only pero `--dev` falla en runtime con mensaje
|
||||
# claro (WASM_BINARY=None). Mantiene `cargo test --workspace` rápido sin env vars.
|
||||
wasm-build = ["origin-chain-runtime/wasm-build"]
|
||||
runtime-benchmarks = ["origin-chain-runtime/runtime-benchmarks"]
|
||||
@@ -35,6 +35,26 @@
|
||||
//! posibles canonical están a la vista canonical, BM V2 incluida canonical.
|
||||
|
||||
mod chain_spec;
|
||||
// Slice 4 Paso 4c (v0.0.49): módulos sc-service `service.rs` + `rpc.rs` escritos
|
||||
// pero NO compilados aún — ver bloqueo arquitectural documentado abajo.
|
||||
//
|
||||
// BLOQUEO (hallazgo v0.0.49): las crates sc-*/sp- consensus PUBLICADAS en
|
||||
// crates.io (sc-consensus-aura 0.52.0 + sp-consensus-aura 0.45.0) tienen una API
|
||||
// DISTINTA al git tag polkadot-stable2509-3 bajo el MISMO número de versión.
|
||||
// El tag usa `sc_consensus_aura::standalone::slot_duration_at` +
|
||||
// `sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration`;
|
||||
// las publicadas tienen `slot_duration_at` en root y NO tienen un slot
|
||||
// `InherentDataProvider` (Slot no implementa el trait). polkadot-sdk reusa
|
||||
// números de versión con cambios git no publicados.
|
||||
//
|
||||
// Construir un node service real requiere migrar TODO el stack sc-*/sp- consensus
|
||||
// a git sources del tag stable2509-3 — la misma cirugía de duplicate-crate que
|
||||
// golpeó pallet-revive (Ship 2 v0.0.39). Es una decisión arquitectural para David.
|
||||
// Ver docs/SLICE_4_SC_SERVICE_IMPLEMENTATION_PLAN_V1.md §10 (finding) para opciones.
|
||||
//
|
||||
// `service.rs`/`rpc.rs` se conservan como archivos (no `mod`-declarados) para la
|
||||
// siguiente fase. El core2 yanked unblock (Cargo.toml + vendor/) SÍ quedó resuelto
|
||||
// — era el blocker real de resolución que difirió sc-service 3 sesiones.
|
||||
|
||||
use clap::{Parser, Subcommand};
|
||||
use origin_chain_runtime::{
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
//! Origin Chain node RPC (Slice 4 Paso 4c).
|
||||
//!
|
||||
//! Patrón estándar solochain-template `polkadot-stable2509-3`. Expone System
|
||||
//! (account nonce) + TransactionPayment (fee queries) sobre el client del node.
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use jsonrpsee::RpcModule;
|
||||
use origin_chain_runtime::{opaque::Block, AccountId, Balance, Nonce};
|
||||
use sc_transaction_pool_api::TransactionPool;
|
||||
use sp_api::ProvideRuntimeApi;
|
||||
use sp_block_builder::BlockBuilder;
|
||||
use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata};
|
||||
|
||||
/// Dependencias completas para construir los RPC del node.
|
||||
pub struct FullDeps<C, P> {
|
||||
/// El client del node.
|
||||
pub client: Arc<C>,
|
||||
/// El transaction pool del node.
|
||||
pub pool: Arc<P>,
|
||||
}
|
||||
|
||||
/// Instancia los RPC handlers completos (System + TransactionPayment).
|
||||
pub fn create_full<C, P>(
|
||||
deps: FullDeps<C, P>,
|
||||
) -> Result<RpcModule<()>, Box<dyn std::error::Error + Send + Sync>>
|
||||
where
|
||||
C: ProvideRuntimeApi<Block>
|
||||
+ HeaderBackend<Block>
|
||||
+ HeaderMetadata<Block, Error = BlockChainError>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
C::Api: substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>
|
||||
+ pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<Block, Balance>
|
||||
+ BlockBuilder<Block>,
|
||||
P: TransactionPool + 'static,
|
||||
{
|
||||
use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer};
|
||||
use substrate_frame_rpc_system::{System, SystemApiServer};
|
||||
|
||||
let mut module = RpcModule::new(());
|
||||
let FullDeps { client, pool } = deps;
|
||||
|
||||
module.merge(System::new(client.clone(), pool).into_rpc())?;
|
||||
module.merge(TransactionPayment::new(client).into_rpc())?;
|
||||
|
||||
Ok(module)
|
||||
}
|
||||
@@ -0,0 +1,328 @@
|
||||
//! Origin Chain node service (Slice 4 Paso 4c).
|
||||
//!
|
||||
//! Verbatim del solochain-template `polkadot-stable2509-3`
|
||||
//! (`templates/solochain/node/src/service.rs`), con un único cambio: el import
|
||||
//! del runtime apunta a `origin_chain_runtime`. Aura (block production) + Grandpa
|
||||
//! (finality) + JSON-RPC + libp2p networking + telemetry.
|
||||
|
||||
use futures::FutureExt;
|
||||
use sc_client_api::{Backend, BlockBackend};
|
||||
use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams};
|
||||
use sc_consensus_grandpa::SharedVoterState;
|
||||
use sc_service::{error::Error as ServiceError, Configuration, TaskManager, WarpSyncConfig};
|
||||
use sc_telemetry::{Telemetry, TelemetryWorker};
|
||||
use sc_transaction_pool_api::OffchainTransactionPoolFactory;
|
||||
use origin_chain_runtime::{opaque::Block, RuntimeApi};
|
||||
use sp_consensus_aura::sr25519::AuthorityPair as AuraPair;
|
||||
use std::{sync::Arc, time::Duration};
|
||||
|
||||
pub(crate) type FullClient = sc_service::TFullClient<
|
||||
Block,
|
||||
RuntimeApi,
|
||||
sc_executor::WasmExecutor<sp_io::SubstrateHostFunctions>,
|
||||
>;
|
||||
type FullBackend = sc_service::TFullBackend<Block>;
|
||||
type FullSelectChain = sc_consensus::LongestChain<FullBackend, Block>;
|
||||
|
||||
/// Periodo mínimo de bloques sobre los que se importan/generan justifications.
|
||||
const GRANDPA_JUSTIFICATION_PERIOD: u32 = 512;
|
||||
|
||||
pub type Service = sc_service::PartialComponents<
|
||||
FullClient,
|
||||
FullBackend,
|
||||
FullSelectChain,
|
||||
sc_consensus::DefaultImportQueue<Block>,
|
||||
sc_transaction_pool::TransactionPoolHandle<Block, FullClient>,
|
||||
(
|
||||
sc_consensus_grandpa::GrandpaBlockImport<FullBackend, Block, FullClient, FullSelectChain>,
|
||||
sc_consensus_grandpa::LinkHalf<Block, FullClient, FullSelectChain>,
|
||||
Option<Telemetry>,
|
||||
),
|
||||
>;
|
||||
|
||||
pub fn new_partial(config: &Configuration) -> Result<Service, ServiceError> {
|
||||
let telemetry = config
|
||||
.telemetry_endpoints
|
||||
.clone()
|
||||
.filter(|x| !x.is_empty())
|
||||
.map(|endpoints| -> Result<_, sc_telemetry::Error> {
|
||||
let worker = TelemetryWorker::new(16)?;
|
||||
let telemetry = worker.handle().new_telemetry(endpoints);
|
||||
Ok((worker, telemetry))
|
||||
})
|
||||
.transpose()?;
|
||||
|
||||
let executor = sc_service::new_wasm_executor::<sp_io::SubstrateHostFunctions>(&config.executor);
|
||||
let (client, backend, keystore_container, task_manager) =
|
||||
sc_service::new_full_parts::<Block, RuntimeApi, _>(
|
||||
config,
|
||||
telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),
|
||||
executor,
|
||||
)?;
|
||||
let client = Arc::new(client);
|
||||
|
||||
let telemetry = telemetry.map(|(worker, telemetry)| {
|
||||
task_manager.spawn_handle().spawn("telemetry", None, worker.run());
|
||||
telemetry
|
||||
});
|
||||
|
||||
let select_chain = sc_consensus::LongestChain::new(backend.clone());
|
||||
|
||||
let transaction_pool = Arc::from(
|
||||
sc_transaction_pool::Builder::new(
|
||||
task_manager.spawn_essential_handle(),
|
||||
client.clone(),
|
||||
config.role.is_authority().into(),
|
||||
)
|
||||
.with_options(config.transaction_pool.clone())
|
||||
.with_prometheus(config.prometheus_registry())
|
||||
.build(),
|
||||
);
|
||||
|
||||
let (grandpa_block_import, grandpa_link) = sc_consensus_grandpa::block_import(
|
||||
client.clone(),
|
||||
GRANDPA_JUSTIFICATION_PERIOD,
|
||||
&client,
|
||||
select_chain.clone(),
|
||||
telemetry.as_ref().map(|x| x.handle()),
|
||||
)?;
|
||||
|
||||
let cidp_client = client.clone();
|
||||
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(),
|
||||
create_inherent_data_providers: move |parent_hash, _| {
|
||||
let cidp_client = cidp_client.clone();
|
||||
async move {
|
||||
// sc-consensus-aura 0.52: slot_duration_at vive en el root del
|
||||
// crate (no en `standalone::`, que es de versiones posteriores).
|
||||
let slot_duration = sc_consensus_aura::slot_duration_at(
|
||||
&*cidp_client,
|
||||
parent_hash,
|
||||
)?;
|
||||
let timestamp = sp_timestamp::InherentDataProvider::from_system_time();
|
||||
|
||||
// crates.io sp-consensus-aura 0.45: el slot se deriva del
|
||||
// timestamp vía `Slot::from_timestamp` (no existe
|
||||
// `inherents::InherentDataProvider::from_timestamp_and_slot_duration`,
|
||||
// que es de un snapshot git posterior con la misma versión).
|
||||
let slot =
|
||||
sp_consensus_aura::Slot::from_timestamp(*timestamp, slot_duration);
|
||||
|
||||
Ok((slot, timestamp))
|
||||
}
|
||||
},
|
||||
spawner: &task_manager.spawn_essential_handle(),
|
||||
registry: config.prometheus_registry(),
|
||||
check_for_equivocation: Default::default(),
|
||||
telemetry: telemetry.as_ref().map(|x| x.handle()),
|
||||
compatibility_mode: Default::default(),
|
||||
})?;
|
||||
|
||||
Ok(sc_service::PartialComponents {
|
||||
client,
|
||||
backend,
|
||||
task_manager,
|
||||
import_queue,
|
||||
keystore_container,
|
||||
select_chain,
|
||||
transaction_pool,
|
||||
other: (grandpa_block_import, grandpa_link, telemetry),
|
||||
})
|
||||
}
|
||||
|
||||
/// Construye un nuevo service para un full client.
|
||||
pub fn new_full<
|
||||
N: sc_network::NetworkBackend<Block, <Block as sp_runtime::traits::Block>::Hash>,
|
||||
>(
|
||||
config: Configuration,
|
||||
) -> Result<TaskManager, ServiceError> {
|
||||
let sc_service::PartialComponents {
|
||||
client,
|
||||
backend,
|
||||
mut task_manager,
|
||||
import_queue,
|
||||
keystore_container,
|
||||
select_chain,
|
||||
transaction_pool,
|
||||
other: (block_import, grandpa_link, mut telemetry),
|
||||
} = new_partial(&config)?;
|
||||
|
||||
let mut net_config = sc_network::config::FullNetworkConfiguration::<
|
||||
Block,
|
||||
<Block as sp_runtime::traits::Block>::Hash,
|
||||
N,
|
||||
>::new(&config.network, config.prometheus_registry().cloned());
|
||||
let metrics = N::register_notification_metrics(config.prometheus_registry());
|
||||
|
||||
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"),
|
||||
&config.chain_spec,
|
||||
);
|
||||
let (grandpa_protocol_config, grandpa_notification_service) =
|
||||
sc_consensus_grandpa::grandpa_peers_set_config::<_, N>(
|
||||
grandpa_protocol_name.clone(),
|
||||
metrics.clone(),
|
||||
peer_store_handle,
|
||||
);
|
||||
net_config.add_notification_protocol(grandpa_protocol_config);
|
||||
|
||||
let warp_sync = Arc::new(sc_consensus_grandpa::warp_proof::NetworkProvider::new(
|
||||
backend.clone(),
|
||||
grandpa_link.shared_authority_set().clone(),
|
||||
Vec::default(),
|
||||
));
|
||||
|
||||
let (network, system_rpc_tx, tx_handler_controller, sync_service) =
|
||||
sc_service::build_network(sc_service::BuildNetworkParams {
|
||||
config: &config,
|
||||
net_config,
|
||||
client: client.clone(),
|
||||
transaction_pool: transaction_pool.clone(),
|
||||
spawn_handle: task_manager.spawn_handle(),
|
||||
import_queue,
|
||||
block_announce_validator_builder: None,
|
||||
warp_sync_config: Some(WarpSyncConfig::WithProvider(warp_sync)),
|
||||
block_relay: None,
|
||||
metrics,
|
||||
})?;
|
||||
|
||||
if config.offchain_worker.enabled {
|
||||
let offchain_workers =
|
||||
sc_offchain::OffchainWorkers::new(sc_offchain::OffchainWorkerOptions {
|
||||
runtime_api_provider: client.clone(),
|
||||
is_validator: config.role.is_authority(),
|
||||
keystore: Some(keystore_container.keystore()),
|
||||
offchain_db: backend.offchain_storage(),
|
||||
transaction_pool: Some(OffchainTransactionPoolFactory::new(
|
||||
transaction_pool.clone(),
|
||||
)),
|
||||
network_provider: Arc::new(network.clone()),
|
||||
enable_http_requests: true,
|
||||
custom_extensions: |_| vec![],
|
||||
})?;
|
||||
task_manager.spawn_handle().spawn(
|
||||
"offchain-workers-runner",
|
||||
"offchain-worker",
|
||||
offchain_workers.run(client.clone(), task_manager.spawn_handle()).boxed(),
|
||||
);
|
||||
}
|
||||
|
||||
let role = config.role;
|
||||
let force_authoring = config.force_authoring;
|
||||
let backoff_authoring_blocks: Option<()> = None;
|
||||
let name = config.network.node_name.clone();
|
||||
let enable_grandpa = !config.disable_grandpa;
|
||||
let prometheus_registry = config.prometheus_registry().cloned();
|
||||
|
||||
let rpc_extensions_builder = {
|
||||
let client = client.clone();
|
||||
let pool = transaction_pool.clone();
|
||||
|
||||
Box::new(move |_| {
|
||||
let deps = crate::rpc::FullDeps { client: client.clone(), pool: pool.clone() };
|
||||
crate::rpc::create_full(deps).map_err(Into::into)
|
||||
})
|
||||
};
|
||||
|
||||
let _rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams {
|
||||
network: Arc::new(network.clone()),
|
||||
client: client.clone(),
|
||||
keystore: keystore_container.keystore(),
|
||||
task_manager: &mut task_manager,
|
||||
transaction_pool: transaction_pool.clone(),
|
||||
rpc_builder: rpc_extensions_builder,
|
||||
backend,
|
||||
system_rpc_tx,
|
||||
tx_handler_controller,
|
||||
sync_service: sync_service.clone(),
|
||||
config,
|
||||
telemetry: telemetry.as_mut(),
|
||||
})?;
|
||||
|
||||
if role.is_authority() {
|
||||
let proposer_factory = sc_basic_authorship::ProposerFactory::new(
|
||||
task_manager.spawn_handle(),
|
||||
client.clone(),
|
||||
transaction_pool.clone(),
|
||||
prometheus_registry.as_ref(),
|
||||
telemetry.as_ref().map(|x| x.handle()),
|
||||
);
|
||||
|
||||
let slot_duration = sc_consensus_aura::slot_duration(&*client)?;
|
||||
|
||||
let aura = sc_consensus_aura::start_aura::<AuraPair, _, _, _, _, _, _, _, _, _, _>(
|
||||
StartAuraParams {
|
||||
slot_duration,
|
||||
client,
|
||||
select_chain,
|
||||
block_import,
|
||||
proposer_factory,
|
||||
create_inherent_data_providers: move |_, ()| async move {
|
||||
let timestamp = sp_timestamp::InherentDataProvider::from_system_time();
|
||||
|
||||
// Mismo patrón que el import_queue CIDP (crates.io 0.45 API).
|
||||
let slot =
|
||||
sp_consensus_aura::Slot::from_timestamp(*timestamp, slot_duration);
|
||||
|
||||
Ok((slot, timestamp))
|
||||
},
|
||||
force_authoring,
|
||||
backoff_authoring_blocks,
|
||||
keystore: keystore_container.keystore(),
|
||||
sync_oracle: sync_service.clone(),
|
||||
justification_sync_link: sync_service.clone(),
|
||||
block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32),
|
||||
max_block_proposal_slot_portion: None,
|
||||
telemetry: telemetry.as_ref().map(|x| x.handle()),
|
||||
compatibility_mode: Default::default(),
|
||||
},
|
||||
)?;
|
||||
|
||||
// La tarea de authoring de AURA es esencial: si falla, baja el service.
|
||||
task_manager
|
||||
.spawn_essential_handle()
|
||||
.spawn_blocking("aura", Some("block-authoring"), aura);
|
||||
}
|
||||
|
||||
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 grandpa_config = sc_consensus_grandpa::Config {
|
||||
gossip_duration: Duration::from_millis(333),
|
||||
justification_generation_period: GRANDPA_JUSTIFICATION_PERIOD,
|
||||
name: Some(name),
|
||||
observer_enabled: false,
|
||||
keystore,
|
||||
local_role: role,
|
||||
telemetry: telemetry.as_ref().map(|x| x.handle()),
|
||||
protocol_name: grandpa_protocol_name,
|
||||
};
|
||||
|
||||
let grandpa_config = sc_consensus_grandpa::GrandpaParams {
|
||||
config: grandpa_config,
|
||||
link: grandpa_link,
|
||||
network,
|
||||
sync: Arc::new(sync_service),
|
||||
notification_service: grandpa_notification_service,
|
||||
voting_rule: sc_consensus_grandpa::VotingRulesBuilder::default().build(),
|
||||
prometheus_registry,
|
||||
shared_voter_state: SharedVoterState::empty(),
|
||||
telemetry: telemetry.as_ref().map(|x| x.handle()),
|
||||
offchain_tx_pool_factory: OffchainTransactionPoolFactory::new(transaction_pool),
|
||||
};
|
||||
|
||||
// La tarea del voter de GRANDPA es infalible: si falla, baja el service.
|
||||
task_manager.spawn_essential_handle().spawn_blocking(
|
||||
"grandpa-voter",
|
||||
None,
|
||||
sc_consensus_grandpa::run_grandpa_voter(grandpa_config)?,
|
||||
);
|
||||
}
|
||||
|
||||
Ok(task_manager)
|
||||
}
|
||||
Reference in new issue
Block a user