diff --git a/Cargo.lock b/Cargo.lock index 67640f55..235e35f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -519,7 +519,7 @@ dependencies = [ "ark-ff", "ark-serialize", "ark-std", - "ark-transcript", + "ark-transcript 0.0.2 (git+https://github.com/w3f/ring-vrf?rev=e9782f9)", "digest 0.10.7", "getrandom_or_panic", "zeroize", @@ -584,6 +584,19 @@ dependencies = [ "sha3", ] +[[package]] +name = "ark-transcript" +version = "0.0.2" +source = "git+https://github.com/w3f/ring-vrf#0fef8266d851932ad25d6b41bc4b34d834d1e11d" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "digest 0.10.7", + "rand_core 0.6.4", + "sha3", +] + [[package]] name = "array-bytes" version = "4.2.0" @@ -665,6 +678,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "assert_matches" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" + [[package]] name = "async-channel" version = "1.9.0" @@ -1644,7 +1663,7 @@ dependencies = [ [[package]] name = "common" version = "0.1.0" -source = "git+https://github.com/w3f/ring-proof#665f5f51af5734c7b6d90b985dd6861d4c5b4752" +source = "git+https://github.com/w3f/ring-proof#31658d1f5b88e106c969557c36c821aff46b2236" dependencies = [ "ark-ec", "ark-ff", @@ -1653,8 +1672,7 @@ dependencies = [ "ark-std", "fflonk", "getrandom_or_panic", - "merlin", - "rand_chacha 0.3.1", + "rand_core 0.6.4", ] [[package]] @@ -2503,7 +2521,7 @@ dependencies = [ "ark-secret-scalar", "ark-serialize", "ark-std", - "ark-transcript", + "ark-transcript 0.0.2 (git+https://github.com/w3f/ring-vrf?rev=e9782f9)", "arrayvec 0.7.6", "zeroize", ] @@ -9745,7 +9763,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", - "itertools 0.12.1", + "itertools 0.11.0", "proc-macro2", "quote", "syn 2.0.76", @@ -10142,18 +10160,18 @@ dependencies = [ [[package]] name = "ring" version = "0.1.0" -source = "git+https://github.com/w3f/ring-proof#665f5f51af5734c7b6d90b985dd6861d4c5b4752" +source = "git+https://github.com/w3f/ring-proof#31658d1f5b88e106c969557c36c821aff46b2236" dependencies = [ "ark-ec", "ark-ff", "ark-poly", "ark-serialize", "ark-std", + "ark-transcript 0.0.2 (git+https://github.com/w3f/ring-vrf)", "arrayvec 0.7.6", "blake2 0.10.6", "common", "fflonk", - "merlin", ] [[package]] @@ -11065,6 +11083,41 @@ dependencies = [ "thiserror", ] +[[package]] +name = "sc-consensus-manual-seal" +version = "0.35.0" +source = "git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot-v1.7.0#851c824dc7a8e7e6db2d0c9fb29d232f2f45198a" +dependencies = [ + "assert_matches", + "async-trait", + "futures 0.3.30", + "futures-timer", + "jsonrpsee 0.20.4", + "log", + "parity-scale-codec", + "sc-client-api", + "sc-consensus", + "sc-consensus-aura", + "sc-consensus-babe", + "sc-consensus-epochs", + "sc-transaction-pool", + "sc-transaction-pool-api", + "serde", + "sp-api", + "sp-blockchain", + "sp-consensus", + "sp-consensus-aura", + "sp-consensus-babe", + "sp-consensus-slots", + "sp-core", + "sp-inherents", + "sp-keystore", + "sp-runtime", + "sp-timestamp", + "substrate-prometheus-endpoint", + "thiserror", +] + [[package]] name = "sc-consensus-slots" version = "0.33.0" @@ -12051,9 +12104,9 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.209" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] @@ -12069,9 +12122,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.209" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", @@ -12822,7 +12875,7 @@ dependencies = [ [[package]] name = "sp-crypto-ec-utils" version = "0.10.0" -source = "git+https://github.com/paritytech/polkadot-sdk#f7504cec1689850f2c93176fe81667d650217e1c" +source = "git+https://github.com/paritytech/polkadot-sdk#22bdc3e5d8bcf2f542fcf57cea686f2774cbb626" dependencies = [ "ark-bls12-377", "ark-bls12-377-ext", @@ -12898,7 +12951,7 @@ dependencies = [ [[package]] name = "sp-debug-derive" version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#f7504cec1689850f2c93176fe81667d650217e1c" +source = "git+https://github.com/paritytech/polkadot-sdk#22bdc3e5d8bcf2f542fcf57cea686f2774cbb626" dependencies = [ "proc-macro2", "quote", @@ -12919,7 +12972,7 @@ dependencies = [ [[package]] name = "sp-externalities" version = "0.25.0" -source = "git+https://github.com/paritytech/polkadot-sdk#f7504cec1689850f2c93176fe81667d650217e1c" +source = "git+https://github.com/paritytech/polkadot-sdk#22bdc3e5d8bcf2f542fcf57cea686f2774cbb626" dependencies = [ "environmental", "parity-scale-codec", @@ -13119,7 +13172,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface" version = "24.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#f7504cec1689850f2c93176fe81667d650217e1c" +source = "git+https://github.com/paritytech/polkadot-sdk#22bdc3e5d8bcf2f542fcf57cea686f2774cbb626" dependencies = [ "bytes", "impl-trait-for-tuples", @@ -13151,7 +13204,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" version = "17.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#f7504cec1689850f2c93176fe81667d650217e1c" +source = "git+https://github.com/paritytech/polkadot-sdk#22bdc3e5d8bcf2f542fcf57cea686f2774cbb626" dependencies = [ "Inflector", "expander", @@ -13244,7 +13297,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot [[package]] name = "sp-std" version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#f7504cec1689850f2c93176fe81667d650217e1c" +source = "git+https://github.com/paritytech/polkadot-sdk#22bdc3e5d8bcf2f542fcf57cea686f2774cbb626" [[package]] name = "sp-storage" @@ -13262,7 +13315,7 @@ dependencies = [ [[package]] name = "sp-storage" version = "19.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#f7504cec1689850f2c93176fe81667d650217e1c" +source = "git+https://github.com/paritytech/polkadot-sdk#22bdc3e5d8bcf2f542fcf57cea686f2774cbb626" dependencies = [ "impl-serde", "parity-scale-codec", @@ -13299,7 +13352,7 @@ dependencies = [ [[package]] name = "sp-tracing" version = "16.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#f7504cec1689850f2c93176fe81667d650217e1c" +source = "git+https://github.com/paritytech/polkadot-sdk#22bdc3e5d8bcf2f542fcf57cea686f2774cbb626" dependencies = [ "parity-scale-codec", "tracing", @@ -13399,7 +13452,7 @@ dependencies = [ [[package]] name = "sp-wasm-interface" version = "20.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#f7504cec1689850f2c93176fe81667d650217e1c" +source = "git+https://github.com/paritytech/polkadot-sdk#22bdc3e5d8bcf2f542fcf57cea686f2774cbb626" dependencies = [ "anyhow", "impl-trait-for-tuples", @@ -14410,6 +14463,7 @@ dependencies = [ "sc-consensus-babe-rpc", "sc-consensus-grandpa", "sc-consensus-grandpa-rpc", + "sc-consensus-manual-seal", "sc-consensus-slots", "sc-executor", "sc-network", diff --git a/node/Cargo.toml b/node/Cargo.toml index b58c7ba3..912f1a1f 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -100,7 +100,7 @@ rpc-txpool = { workspace = true } sc-consensus-babe-rpc = { workspace = true } sc-consensus-grandpa-rpc = { workspace = true } sc-consensus-slots = { workspace = true } - +sc-consensus-manual-seal = { workspace = true } sp-consensus = { workspace = true } sp-transaction-storage-proof = { workspace = true } @@ -136,4 +136,5 @@ sql = ["fc-db/sql", "fc-mapping-sync/sql"] testnet = ["tangle-testnet-runtime"] txpool = ["fc-rpc/txpool"] fast-runtime = ["tangle-testnet-runtime/fast-runtime", "tangle-runtime/fast-runtime"] -metadata-hash = ["tangle-testnet-runtime?/metadata-hash", "tangle-runtime/metadata-hash"] \ No newline at end of file +metadata-hash = ["tangle-testnet-runtime?/metadata-hash", "tangle-runtime/metadata-hash"] +instant-seal = [] \ No newline at end of file diff --git a/node/src/service.rs b/node/src/service.rs index 336b8e55..0a51a54d 100644 --- a/node/src/service.rs +++ b/node/src/service.rs @@ -286,7 +286,9 @@ pub struct RunFullParams { pub debug_output: Option, pub auto_insert_keys: bool, } + /// Builds a new service for a full client. +#[cfg(not(feature = "instant-seal"))] pub async fn new_full( RunFullParams { mut config, eth_config, rpc_config, debug_output: _, auto_insert_keys }: RunFullParams, ) -> Result { @@ -679,6 +681,326 @@ pub async fn new_full( Ok(task_manager) } +#[cfg(feature = "instant-seal")] +pub async fn new_full( + RunFullParams { mut config, eth_config, rpc_config, debug_output: _, auto_insert_keys }: RunFullParams, +) -> Result { + let sc_service::PartialComponents { + client, + backend, + mut task_manager, + import_queue, + keystore_container, + select_chain, + transaction_pool, + other: + ( + mut telemetry, + block_import, + grandpa_link, + babe_link, + frontier_backend, + overrides, + babe_worker_handle, + ), + } = new_partial(&config, ð_config)?; + + let FrontierPartialComponents { filter_pool, fee_history_cache, fee_history_cache_limit } = + new_frontier_partial(ð_config)?; + + let mut net_config = sc_network::config::FullNetworkConfiguration::new(&config.network); + + 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(grandpa_protocol_name.clone()); + + 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, network_starter, 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_params: Some(sc_service::WarpSyncParams::WithProvider(warp_sync)), + block_relay: None, + })?; + + let role = config.role.clone(); + let force_authoring = config.force_authoring; + let name = config.network.node_name.clone(); + let enable_grandpa = !config.disable_grandpa; + let prometheus_registry = config.prometheus_registry().cloned(); + + if config.offchain_worker.enabled { + task_manager.spawn_handle().spawn( + "offchain-workers-runner", + "offchain-work", + sc_offchain::OffchainWorkers::new(sc_offchain::OffchainWorkerOptions { + runtime_api_provider: client.clone(), + keystore: Some(keystore_container.keystore()), + offchain_db: backend.offchain_storage(), + transaction_pool: Some(OffchainTransactionPoolFactory::new( + transaction_pool.clone(), + )), + network_provider: network.clone(), + is_validator: role.is_authority(), + enable_http_requests: true, + custom_extensions: move |_| vec![], + }) + .run(client.clone(), task_manager.spawn_handle()) + .boxed(), + ); + } + + // Sinks for pubsub notifications. + // Everytime a new subscription is created, a new mpsc channel is added to the sink pool. + // The MappingSyncWorker sends through the channel on block import and the subscription emits a + // notification to the subscriber on receiving a message through this channel. This way we avoid + // race conditions when using native substrate block import notification stream. + let pubsub_notification_sinks: fc_mapping_sync::EthereumBlockNotificationSinks< + fc_mapping_sync::EthereumBlockNotification, + > = Default::default(); + let pubsub_notification_sinks = Arc::new(pubsub_notification_sinks); + + // for ethereum-compatibility rpc. + config.rpc_id_provider = Some(Box::new(fc_rpc::EthereumSubIdProvider)); + + let slot_duration = babe_link.config().slot_duration(); + let target_gas_price = eth_config.target_gas_price; + + let ethapi_cmd = rpc_config.ethapi.clone(); + let tracing_requesters = + if ethapi_cmd.contains(&EthApi::Debug) || ethapi_cmd.contains(&EthApi::Trace) { + crate::rpc::tracing::spawn_tracing_tasks( + &task_manager, + client.clone(), + backend.clone(), + frontier_backend.clone(), + overrides.clone(), + &rpc_config, + prometheus_registry.clone(), + ) + } else { + crate::rpc::tracing::RpcRequesters { debug: None, trace: None } + }; + + let pending_create_inherent_data_providers = move |_, ()| async move { + let current = sp_timestamp::InherentDataProvider::from_system_time(); + let next_slot = current.timestamp().as_millis() + slot_duration.as_millis(); + let timestamp = sp_timestamp::InherentDataProvider::new(next_slot.into()); + let slot = + sp_consensus_babe::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + *timestamp, + slot_duration, + ); + let dynamic_fee = fp_dynamic_fee::InherentDataProvider(U256::from(target_gas_price)); + Ok((slot, timestamp, dynamic_fee)) + }; + + let eth_rpc_params = crate::rpc::EthDeps { + client: client.clone(), + pool: transaction_pool.clone(), + graph: transaction_pool.pool().clone(), + converter: Some(TransactionConverter), + is_authority: config.role.is_authority(), + enable_dev_signer: eth_config.enable_dev_signer, + network: network.clone(), + sync: sync_service.clone(), + frontier_backend: match frontier_backend.clone() { + fc_db::Backend::KeyValue(b) => Arc::new(b), + fc_db::Backend::Sql(b) => Arc::new(b), + }, + overrides: overrides.clone(), + block_data_cache: Arc::new(fc_rpc::EthBlockDataCacheTask::new( + task_manager.spawn_handle(), + overrides.clone(), + eth_config.eth_log_block_cache, + eth_config.eth_statuses_cache, + prometheus_registry.clone(), + )), + filter_pool: filter_pool.clone(), + max_past_logs: eth_config.max_past_logs, + fee_history_cache: fee_history_cache.clone(), + fee_history_cache_limit, + execute_gas_limit_multiplier: eth_config.execute_gas_limit_multiplier, + forced_parent_hashes: None, + tracing_config: Some(crate::rpc::eth::TracingConfig { + tracing_requesters: tracing_requesters.clone(), + trace_filter_max_count: rpc_config.ethapi_trace_max_count, + }), + pending_create_inherent_data_providers, + }; + + let keystore = keystore_container.keystore(); + let select_chain_clone = select_chain.clone(); + let rpc_builder = { + let client = client.clone(); + let pool = transaction_pool.clone(); + let pubsub_notification_sinks = pubsub_notification_sinks.clone(); + let justification_stream = grandpa_link.justification_stream(); + let shared_authority_set = grandpa_link.shared_authority_set().clone(); + let shared_voter_state = sc_consensus_grandpa::SharedVoterState::empty(); + let _shared_voter_state2 = shared_voter_state.clone(); + + let finality_proof_provider = sc_consensus_grandpa::FinalityProofProvider::new_for_service( + backend.clone(), + Some(shared_authority_set.clone()), + ); + + Box::new( + move |deny_unsafe, subscription_task_executor: sc_rpc::SubscriptionTaskExecutor| { + let deps = crate::rpc::FullDeps { + client: client.clone(), + pool: pool.clone(), + deny_unsafe, + eth: eth_rpc_params.clone(), + babe: crate::rpc::BabeDeps { + keystore: keystore.clone(), + babe_worker_handle: babe_worker_handle.clone(), + }, + select_chain: select_chain_clone.clone(), + grandpa: crate::rpc::GrandpaDeps { + shared_voter_state: shared_voter_state.clone(), + shared_authority_set: shared_authority_set.clone(), + justification_stream: justification_stream.clone(), + subscription_executor: subscription_task_executor.clone(), + finality_provider: finality_proof_provider.clone(), + }, + }; + + crate::rpc::create_full( + deps, + subscription_task_executor, + pubsub_notification_sinks.clone(), + ) + .map_err(Into::into) + }, + ) + }; + + spawn_frontier_tasks( + &task_manager, + client.clone(), + backend.clone(), + frontier_backend, + filter_pool, + overrides, + fee_history_cache, + fee_history_cache_limit, + sync_service.clone(), + pubsub_notification_sinks, + ) + .await; + + let params = sc_service::SpawnTasksParams { + network: network.clone(), + client: client.clone(), + keystore: keystore_container.keystore(), + task_manager: &mut task_manager, + transaction_pool: transaction_pool.clone(), + rpc_builder, + backend: backend.clone(), + system_rpc_tx, + tx_handler_controller, + sync_service: sync_service.clone(), + config, + telemetry: telemetry.as_mut(), + }; + let _rpc_handlers = sc_service::spawn_tasks(params)?; + + if role.is_authority() { + let proposer = 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 params = sc_consensus_manual_seal::InstantSealParams { + block_import: client.clone(), + env: proposer, + client, + pool: transaction_pool.clone(), + select_chain, + consensus_data_provider: None, + create_inherent_data_providers: move |_, ()| async move { + Ok(sp_timestamp::InherentDataProvider::from_system_time()) + }, + }; + + let authorship_future = sc_consensus_manual_seal::run_instant_seal(params); + + task_manager.spawn_essential_handle().spawn_blocking( + "instant-seal", + None, + authorship_future, + ); + } + + // if the node isn't actively participating in consensus then it doesn't + // need a keystore, regardless of which protocol we use below. + let keystore = if role.is_authority() { Some(keystore_container.keystore()) } else { None }; + + let grandpa_config = sc_consensus_grandpa::Config { + // FIXME #1578 make this available through chainspec + 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, + }; + + if enable_grandpa { + // start the full GRANDPA voter + // NOTE: non-authorities could run the GRANDPA observer protocol, but at + // this point the full voter should provide better guarantees of block + // and vote data availability than the observer. The observer has not + // been tested extensively yet and having most nodes in a network run it + // could lead to finality stalls. + 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), + }; + + // the GRANDPA voter task is considered infallible, i.e. + // if it fails we take down the service with it. + task_manager.spawn_essential_handle().spawn_blocking( + "grandpa-voter", + None, + sc_consensus_grandpa::run_grandpa_voter(grandpa_config)?, + ); + } + + network_starter.start_network(); + Ok(task_manager) +} + #[allow(clippy::type_complexity)] pub fn new_chain_ops( config: &mut Configuration,