diff --git a/node/src/parachain/service.rs b/node/src/parachain/service.rs index 88049293..7798a0a6 100644 --- a/node/src/parachain/service.rs +++ b/node/src/parachain/service.rs @@ -1,8 +1,7 @@ //! Parachain Service and ServiceFactory implementation. use cumulus_client_cli::CollatorOptions; -use cumulus_client_consensus_aura::collators::slot_based::{ - self as slot_based, Params as SlotBasedParams, SlotBasedBlockImport as TSlotBasedBlockImport, - SlotBasedBlockImportHandle, +use cumulus_client_consensus_aura::collators::lookahead::{ + self as lookahead, Params as LookaheadParams, }; use cumulus_client_consensus_common::ParachainBlockImport as TParachainBlockImport; use cumulus_client_consensus_relay_chain::Verifier as RelayChainVerifier; @@ -82,10 +81,7 @@ type ParachainClient = TFullClient; type FrontierBlockImport = - TFrontierBlockImport, ParachainClient>; - -type SlotBasedBlockImport = - TSlotBasedBlockImport>, ParachainClient>; + TFrontierBlockImport>, ParachainClient>; type ParachainBlockImport = TParachainBlockImport, ParachainBackend>; @@ -98,8 +94,6 @@ type Service = PartialComponents< sc_transaction_pool::TransactionPoolHandle>, ( ParachainBlockImport, - SlotBasedBlockImportHandle, - // SlotBasedBlockImport, ParachainClient>, Option, Option, Option, @@ -202,6 +196,11 @@ where config, telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), executor, + // Author uses ProposerFactory::with_proof_recording; the importer MUST also record + // proof so cumulus-pallet-weight-reclaim writes an identical frame_system::BlockWeight + // on both paths. Otherwise the intermediate state root (embedded by frontier into the + // `fron` digest) diverges and execute_block fails final_checks ("Digest item must + // match"). true, )?; let client = Arc::new(client); @@ -227,12 +226,8 @@ where .with_prometheus(config.prometheus_registry()) .build(); - let (slot_based_block_import, slot_based_handle) = - SlotBasedBlockImport::new(client.clone(), client.clone()); - let frontier_block_import = - FrontierBlockImport::new(slot_based_block_import.clone(), client.clone()); - let parachain_block_import = - ParachainBlockImport::new(frontier_block_import.clone(), backend.clone()); + let frontier_block_import = FrontierBlockImport::new(client.clone(), client.clone()); + let parachain_block_import = ParachainBlockImport::new(frontier_block_import, backend.clone()); let import_queue = fn_build_import_queue( client.clone(), @@ -253,7 +248,6 @@ where select_chain: (), other: ( parachain_block_import, - slot_based_handle, filter_pool, telemetry, telemetry_worker_handle, @@ -352,7 +346,6 @@ where KeystorePtr, ParaId, CollatorPair, - SlotBasedBlockImportHandle, ) -> Result<(), sc_service::Error>, { let mut parachain_config = prepare_node_config(parachain_config); @@ -363,7 +356,6 @@ where )?; let ( parachain_block_import, - slot_based_handle, filter_pool, mut telemetry, telemetry_worker_handle, @@ -506,6 +498,7 @@ where let overrides = overrides.clone(); let fee_history_cache = fee_history_cache.clone(); let block_data_cache = block_data_cache.clone(); + let pubsub_notification_sinks = pubsub_notification_sinks.clone(); move |subscription_task_executor| { let deps = crate::rpc::FullDeps { @@ -527,6 +520,7 @@ where overrides: overrides.clone(), block_data_cache: block_data_cache.clone(), forced_parent_hashes: None, + pubsub_notification_sinks: pubsub_notification_sinks.clone(), }; if ethapi_cmd.contains(&EthApiCmd::Debug) || ethapi_cmd.contains(&EthApiCmd::Trace) { @@ -602,7 +596,6 @@ where params.keystore_container.keystore(), id, collator_key.expect("Command line arguments do not allow this. qed"), - slot_based_handle, )?; } @@ -751,8 +744,7 @@ where sync_oracle, keystore, para_id, - collator_key, - block_import_handle| { + collator_key| { let spawn_handle = task_manager.spawn_handle(); let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording( @@ -763,6 +755,10 @@ where telemetry.clone(), ); + let overseer_handle = relay_chain_interface + .overseer_handle() + .map_err(|e| sc_service::Error::Application(Box::new(e)))?; + let announce_block = { let sync_service = sync_oracle.clone(); Arc::new(move |hash, data| sync_service.announce_block(hash, data)) @@ -775,7 +771,7 @@ where client.clone(), ); - let params = SlotBasedParams { + let params = LookaheadParams { create_inherent_data_providers: move |_, ()| async move { Ok(()) }, block_import: block_import.clone(), para_client: client.clone(), @@ -787,22 +783,17 @@ where keystore, collator_key, para_id, - // [TODO] + overseer_handle, max_pov_percentage: Some(85), relay_chain_slot_duration: Duration::from_secs(6), proposer: cumulus_client_consensus_proposer::Proposer::new(proposer_factory), collator_service, // We got around 1500ms for proposing authoring_duration: Duration::from_millis(2000), - // collation_request_receiver: None, reinitialize: false, - slot_offset: Duration::from_secs(1), - spawner: task_manager.spawn_handle(), - export_pov: None, - block_import_handle, }; - slot_based::run::< + let fut = lookahead::run::< Block, sp_consensus_aura::sr25519::AuthorityPair, _, @@ -813,9 +804,10 @@ where _, _, _, - _, >(params); + task_manager.spawn_essential_handle().spawn("aura", None, fut); + Ok(()) }, ) diff --git a/node/src/rpc.rs b/node/src/rpc.rs index b241c111..b431c13a 100644 --- a/node/src/rpc.rs +++ b/node/src/rpc.rs @@ -92,6 +92,14 @@ pub struct FullDeps { pub block_data_cache: Arc>, /// Mandated parent hashes for a given block hash. pub forced_parent_hashes: Option>, + /// Shared sink list — must be the same Arc passed to `MappingSyncWorker`, + /// otherwise `eth_subscribe("newHeads"/"logs")` returns a sub ID but never + /// delivers notifications. + pub pubsub_notification_sinks: Arc< + fc_mapping_sync::EthereumBlockNotificationSinks< + fc_mapping_sync::EthereumBlockNotification, + >, + >, } pub struct TracingConfig { @@ -161,6 +169,7 @@ where overrides, block_data_cache, forced_parent_hashes, + pubsub_notification_sinks, } = deps; io.merge(System::new(Arc::clone(&client), Arc::clone(&pool)).into_rpc())?; @@ -251,11 +260,6 @@ where .into_rpc(), )?; - let pubsub_notification_sinks: fc_mapping_sync::EthereumBlockNotificationSinks< - fc_mapping_sync::EthereumBlockNotification, - > = Default::default(); - let pubsub_notification_sinks = Arc::new(pubsub_notification_sinks); - io.merge(PeaqStorage::new(Arc::clone(&client)).into_rpc())?; io.merge(PeaqDID::new(Arc::clone(&client)).into_rpc())?; io.merge(PeaqRBAC::new(Arc::clone(&client)).into_rpc())?; diff --git a/runtime/common/src/payment.rs b/runtime/common/src/payment.rs index 43773b06..91e44044 100644 --- a/runtime/common/src/payment.rs +++ b/runtime/common/src/payment.rs @@ -77,7 +77,7 @@ where let tx_fee = total_fee.saturating_add(eot_fee); // Check if user can withdraw in any valid currency. - let currency_id = PCPC::ensure_can_withdraw(who, tx_fee)?; + let currency_id = PCPC::resolve_and_swap_fee_currency(who, tx_fee)?; let native_currency_id = PeaqAssetId::default().try_into().ok().unwrap(); if currency_id != native_currency_id { log!( @@ -132,7 +132,6 @@ where Ok(()) } - // [TODO] Need to check... fn can_withdraw_fee( who: &::AccountId, _call: &::RuntimeCall, @@ -143,8 +142,11 @@ where if fee.is_zero() { return Ok(()); } - // Check if user can withdraw in any valid currency. - let currency_id = PCPC::ensure_can_withdraw(who, fee)?; + // Read-only check that the fee is payable in SOME currency, WITHOUT executing the swap. + // can_withdraw_fee runs in `validate` (mempool), which must be side-effect-free; the real + // swap happens later in withdraw_fee (`prepare`). Calling the swap-executing + // resolve_and_swap_fee_currency here would swap in validate AND again in withdraw_fee. + let (currency_id, _) = PCPC::check_currencies_n_priorities(who, fee)?; let native_currency_id = PeaqAssetId::default().try_into().ok().unwrap(); if currency_id != native_currency_id { log!( @@ -206,9 +208,11 @@ pub trait PeaqMultiCurrenciesPaymentConvert { type AssetIdToZenlinkId: Convert>; - /// This method checks if the fee can be withdrawn in any currency and returns the asset_id - /// of the choosen currency in dependency of the priority-list and availability of tokens. - fn ensure_can_withdraw( + /// Resolves which currency pays the fee (per the priority list) and, if it is a non-native + /// currency, EXECUTES the DEX swap to native so the caller can then withdraw it. This MUTATES + /// chain state, so it must NOT be called from the `validate` phase — use the read-only + /// `check_currencies_n_priorities` there. Returns the asset_id of the chosen source currency. + fn resolve_and_swap_fee_currency( who: &Self::AccountId, tx_fee: BalanceOfA, ) -> Result { diff --git a/runtime/common/src/wrapper.rs b/runtime/common/src/wrapper.rs index 0ca4817e..f5a1ffe9 100644 --- a/runtime/common/src/wrapper.rs +++ b/runtime/common/src/wrapper.rs @@ -146,7 +146,11 @@ where asset_id, who, amount, - Preservation::Protect, // TODO What does this do? + // 1.7.2 parity: the old fungibles::burn_from hardcoded Expendable + // (balance may drop to 0 and the account may be reaped). Protect would + // enforce the ED floor, making non-native withdraws that used to succeed + // fail with FundsUnavailable. Also consistent with slash() below. + Preservation::Expendable, Precision::Exact, Fortitude::Polite, ); diff --git a/runtime/krest/src/lib.rs b/runtime/krest/src/lib.rs index 4c6fbf85..b008eac3 100644 --- a/runtime/krest/src/lib.rs +++ b/runtime/krest/src/lib.rs @@ -1,4 +1,7 @@ #![cfg_attr(not(feature = "std"), no_std)] +// Currently, we sunset the krest network. Therefore, after this release, we can remove the +// krest runtime module to speed up the build time. + // `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. #![recursion_limit = "256"] @@ -183,10 +186,10 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // `spec_version`, and `authoring_version` are the same between Wasm and native. // This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use // the compatible custom types. - spec_version: 107, + spec_version: 108, impl_version: 1, apis: RUNTIME_API_VERSIONS, - transaction_version: 1, + transaction_version: 2, system_version: 1, }; @@ -609,6 +612,14 @@ type RootOrTreasuryCouncilOrigin = EitherOfDiverse< pallet_collective::EnsureProportionMoreThan, >; +// Treasury spends require root or a council 3/5 supermajority. The stable2503 +// base gated this at council >1/2; deliberately tightened to 3/5 here. +// RejectOrigin is intentionally left at the looser >1/2. +type RootOrTreasuryCouncilSpendOrigin = EitherOfDiverse< + EnsureRoot, + pallet_collective::EnsureProportionAtLeast, +>; + impl pallet_treasury::Config for Runtime { type PalletId = TreasuryPalletId; type Currency = Balances; @@ -619,7 +630,7 @@ impl pallet_treasury::Config for Runtime { type SpendFunds = (); type WeightInfo = pallet_treasury::weights::SubstrateWeight; type MaxApprovals = MaxApprovals; - type SpendOrigin = EnsureWithSuccess; + type SpendOrigin = EnsureWithSuccess; type RuntimeEvent = RuntimeEvent; type AssetKind = (); @@ -663,8 +674,8 @@ impl> FindAuthor for FindAuthorTruncated { /// Current approximation of the gas/s consumption considering /// EVM execution over compiled WASM (on 4.4Ghz CPU). -/// Given the 500ms Weight, from which 75% only are used for transactions, -/// the total EVM execution gas limit is: GAS_PER_SECOND * 0.500 * 0.75 ~= 15_000_000. +/// Given the 2s Weight, from which 90% only are used for transactions, +/// the total EVM execution gas limit is: GAS_PER_SECOND * 2.0 * 0.90 ~= 72_000_000. pub const GAS_PER_SECOND: u64 = 40_000_000; /// Approximate ratio of the amount of Weight per Gas. diff --git a/runtime/peaq-dev/src/lib.rs b/runtime/peaq-dev/src/lib.rs index 2cdd92a3..18450734 100644 --- a/runtime/peaq-dev/src/lib.rs +++ b/runtime/peaq-dev/src/lib.rs @@ -184,10 +184,10 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // `spec_version`, and `authoring_version` are the same between Wasm and native. // This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use // the compatible custom types. - spec_version: 107, + spec_version: 108, impl_version: 1, apis: RUNTIME_API_VERSIONS, - transaction_version: 1, + transaction_version: 2, system_version: 1, }; @@ -614,6 +614,14 @@ type RootOrTreasuryCouncilOrigin = EitherOfDiverse< pallet_collective::EnsureProportionMoreThan, >; +// Treasury spends require root or a council 3/5 supermajority. The stable2503 +// base gated this at council >1/2; deliberately tightened to 3/5 here. +// RejectOrigin is intentionally left at the looser >1/2. +type RootOrTreasuryCouncilSpendOrigin = EitherOfDiverse< + EnsureRoot, + pallet_collective::EnsureProportionAtLeast, +>; + impl pallet_treasury::Config for Runtime { type PalletId = TreasuryPalletId; type Currency = Balances; @@ -624,7 +632,7 @@ impl pallet_treasury::Config for Runtime { type SpendFunds = (); type WeightInfo = pallet_treasury::weights::SubstrateWeight; type MaxApprovals = MaxApprovals; - type SpendOrigin = EnsureWithSuccess; + type SpendOrigin = EnsureWithSuccess; type RuntimeEvent = RuntimeEvent; type AssetKind = (); @@ -668,8 +676,8 @@ impl> FindAuthor for FindAuthorTruncated { /// Current approximation of the gas/s consumption considering /// EVM execution over compiled WASM (on 4.4Ghz CPU). -/// Given the 500ms Weight, from which 75% only are used for transactions, -/// the total EVM execution gas limit is: GAS_PER_SECOND * 0.500 * 0.75 ~= 15_000_000. +/// Given the 2s Weight, from which 90% only are used for transactions, +/// the total EVM execution gas limit is: GAS_PER_SECOND * 2.0 * 0.90 ~= 72_000_000. pub const GAS_PER_SECOND: u64 = 40_000_000; /// Approximate ratio of the amount of Weight per Gas. diff --git a/runtime/peaq/src/lib.rs b/runtime/peaq/src/lib.rs index 1bb14a0a..0229aa77 100644 --- a/runtime/peaq/src/lib.rs +++ b/runtime/peaq/src/lib.rs @@ -210,10 +210,10 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // `spec_version`, and `authoring_version` are the same between Wasm and native. // This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use // the compatible custom types. - spec_version: 111, + spec_version: 112, impl_version: 1, apis: RUNTIME_API_VERSIONS, - transaction_version: 1, + transaction_version: 2, system_version: 1, }; @@ -635,6 +635,14 @@ type RootOrTreasuryCouncilOrigin = EitherOfDiverse< pallet_collective::EnsureProportionMoreThan, >; +// Treasury spends require root or a council 3/5 supermajority. The stable2503 +// base gated this at council >1/2; deliberately tightened to 3/5 here. +// RejectOrigin is intentionally left at the looser >1/2. +type RootOrTreasuryCouncilSpendOrigin = EitherOfDiverse< + EnsureRoot, + pallet_collective::EnsureProportionAtLeast, +>; + impl pallet_treasury::Config for Runtime { type PalletId = TreasuryPalletId; type Currency = Balances; @@ -645,7 +653,7 @@ impl pallet_treasury::Config for Runtime { type SpendFunds = (); type WeightInfo = pallet_treasury::weights::SubstrateWeight; type MaxApprovals = MaxApprovals; - type SpendOrigin = EnsureWithSuccess; + type SpendOrigin = EnsureWithSuccess; type RuntimeEvent = RuntimeEvent; type AssetKind = (); @@ -689,8 +697,8 @@ impl> FindAuthor for FindAuthorTruncated { /// Current approximation of the gas/s consumption considering /// EVM execution over compiled WASM (on 4.4Ghz CPU). -/// Given the 500ms Weight, from which 75% only are used for transactions, -/// the total EVM execution gas limit is: GAS_PER_SECOND * 0.500 * 0.75 ~= 15_000_000. +/// Given the 2s Weight, from which 90% only are used for transactions, +/// the total EVM execution gas limit is: GAS_PER_SECOND * 2.0 * 0.90 ~= 72_000_000. pub const GAS_PER_SECOND: u64 = 40_000_000; /// Approximate ratio of the amount of Weight per Gas.