diff --git a/.github/workflows/misc-sync-templates.yml b/.github/workflows/misc-sync-templates.yml index 3617d6c34a3e..2699ff0fed3f 100644 --- a/.github/workflows/misc-sync-templates.yml +++ b/.github/workflows/misc-sync-templates.yml @@ -148,12 +148,12 @@ jobs: token: ${{ steps.app_token.outputs.token }} add-paths: | ./* - title: "[Don't merge] Update the ${{ matrix.template }} template" + title: "[Don't merge] Update the ${{ matrix.template }} template to ${{ github.event.inputs.crate_release_version }}" body: "The template has NOT been successfully built and needs to be inspected." - branch: "update-template/${{ github.event_name }}" + branch: "update-template/${{ github.event.inputs.crate_release_version }}" - name: Push changes run: | git add -A . - git commit --allow-empty -m "Update template triggered by ${{ github.event_name }}" + git commit --allow-empty -m "Update to ${{ github.event.inputs.crate_release_version }} triggered by ${{ github.event_name }}" git push working-directory: "${{ env.template-path }}" diff --git a/Cargo.lock b/Cargo.lock index 1767245c6abf..82dfd34c2528 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2366,9 +2366,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.4.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "bzip2-sys" @@ -5339,9 +5339,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "fastrlp" @@ -6175,9 +6175,9 @@ checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-timer" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" [[package]] name = "futures-util" @@ -7956,9 +7956,9 @@ dependencies = [ [[package]] name = "litep2p" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adf107268459b653df189050c9ae2301253b9c62ceafa993dc69dad29870155c" +checksum = "7f02542ae3a94b4c4ffa37dc56388c923e286afa3bf65452e3984b50b2a2f316" dependencies = [ "async-trait", "bs58 0.4.0", @@ -7970,7 +7970,7 @@ dependencies = [ "hex-literal", "indexmap 2.2.3", "libc", - "mockall", + "mockall 0.12.1", "multiaddr", "multihash 0.17.0", "network-interface", @@ -8480,11 +8480,26 @@ dependencies = [ "downcast", "fragile", "lazy_static", - "mockall_derive", + "mockall_derive 0.11.4", "predicates 2.1.5", "predicates-tree", ] +[[package]] +name = "mockall" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43766c2b5203b10de348ffe19f7e54564b64f3d6018ff7648d1e2d6d3a0f0a48" +dependencies = [ + "cfg-if", + "downcast", + "fragile", + "lazy_static", + "mockall_derive 0.12.1", + "predicates 3.0.3", + "predicates-tree", +] + [[package]] name = "mockall_derive" version = "0.11.4" @@ -8497,6 +8512,18 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "mockall_derive" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af7cbce79ec385a1d4f54baa90a76401eb15d9cab93685f62e7e9f942aa00ae2" +dependencies = [ + "cfg-if", + "proc-macro2 1.0.82", + "quote 1.0.35", + "syn 2.0.61", +] + [[package]] name = "multiaddr" version = "0.17.1" @@ -16817,7 +16844,7 @@ dependencies = [ "futures", "futures-timer", "log", - "mockall", + "mockall 0.11.4", "parking_lot 0.12.1", "sc-client-api", "sc-network-types", @@ -17342,7 +17369,7 @@ dependencies = [ "linked_hash_set", "litep2p", "log", - "mockall", + "mockall 0.11.4", "multistream-select", "once_cell", "parity-scale-codec", @@ -17480,7 +17507,7 @@ dependencies = [ "futures-timer", "libp2p", "log", - "mockall", + "mockall 0.11.4", "parity-scale-codec", "prost 0.12.4", "prost-build 0.12.4", @@ -18231,9 +18258,9 @@ dependencies = [ [[package]] name = "sctp-proto" -version = "0.1.7" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f64cef148d3295c730c3cb340b0b252a4d570b1c7d4bf0808f88540b0a888bc" +checksum = "b6220f78bb44c15f326b0596113305f6101097a18755d53727a575c97e09fb24" dependencies = [ "bytes", "crc", @@ -18802,9 +18829,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smol" @@ -20679,17 +20706,17 @@ dependencies = [ [[package]] name = "str0m" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3f10d3f68e60168d81110410428a435dbde28cc5525f5f7c6fdec92dbdc2800" +checksum = "6706347e49b13373f7ddfafad47df7583ed52083d6fc8a594eb2c80497ef959d" dependencies = [ "combine", "crc", + "fastrand 2.1.0", "hmac 0.12.1", "once_cell", "openssl", "openssl-sys", - "rand 0.8.5", "sctp-proto", "serde", "sha-1 0.10.1", @@ -21361,7 +21388,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" dependencies = [ "cfg-if", - "fastrand 2.0.0", + "fastrand 2.1.0", "redox_syscall 0.4.1", "rustix 0.38.21", "windows-sys 0.48.0", @@ -21553,9 +21580,9 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.50" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] @@ -21582,9 +21609,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2 1.0.82", "quote 1.0.35", @@ -21828,9 +21855,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.8" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ "bytes", "futures-core", @@ -21838,7 +21865,6 @@ dependencies = [ "futures-sink", "pin-project-lite 0.2.12", "tokio", - "tracing", ] [[package]] diff --git a/README.md b/README.md index e139dc0ee076..f15c716a811a 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ ![GitHub stars](https://img.shields.io/github/stars/paritytech/polkadot-sdk)  ![GitHub forks](https://img.shields.io/github/forks/paritytech/polkadot-sdk) + [![StackExchange](https://img.shields.io/badge/StackExchange-Community%20&%20Support-222222?logo=stackexchange)](https://substrate.stackexchange.com/)  ![GitHub contributors](https://img.shields.io/github/contributors/paritytech/polkadot-sdk)  ![GitHub commit activity](https://img.shields.io/github/commit-activity/m/paritytech/polkadot-sdk) ![GitHub lines of code](https://tokei.rs/b1/github/paritytech/polkadot-sdk)   @@ -30,7 +31,7 @@ forks](https://img.shields.io/github/forks/paritytech/polkadot-sdk) ## 🚀 Releases -> [!NOTE] +> [!NOTE] > Our release process is still Work-In-Progress and may not yet reflect the aspired outline > here. @@ -62,9 +63,10 @@ Conduct](./docs/contributor/CODE_OF_CONDUCT.md). ### 👾 Ready to Contribute? -Take a look at the issues labeled with [`mentor`](https://github.com/paritytech/polkadot-sdk/labels/C1-mentor) (or alternatively [this](https://mentor.tasty.limo/) page, created by one of -the maintainers) label to get started! We always recognize valuable contributions by proposing an -on-chain tip to the Polkadot network as a token of our appreciation. +Take a look at the issues labeled with [`mentor`](https://github.com/paritytech/polkadot-sdk/labels/C1-mentor) +(or alternatively [this](https://mentor.tasty.limo/) page, created by one of the maintainers) label to get started! +We always recognize valuable contributions by proposing an on-chain tip to the Polkadot network as a token of our +appreciation. ## Polkadot Fellowship diff --git a/bridges/docs/running-relayer.md b/bridges/docs/running-relayer.md index 710810a476e4..594cbc35a106 100644 --- a/bridges/docs/running-relayer.md +++ b/bridges/docs/running-relayer.md @@ -139,7 +139,7 @@ your transactions that are **validated** on top of block, where it is active get becomes expired when the block with the number you have specified during registration is "mined". It is the `validTill` parameter of the `register` call (see below). After that `validTill` block, you may unregister and get your reserved funds back. There's also an intermediate point between those blocks - it is the `validTill - LEASE`, -where `LEASE` is the the chain constant, controlled by the governance. Initially it is set to `300` blocks. +where `LEASE` is the chain constant, controlled by the governance. Initially it is set to `300` blocks. All your transactions, **validated** between the `validTill - LEASE` and `validTill` blocks do not get the priority boost. Also, it is forbidden to specify `validTill` such that the `validTill - currentBlock` is less than the `LEASE`. @@ -156,7 +156,7 @@ than the `LEASE`. | 700 | Inactive | Your message delivery transactions are not boosted | | 701 | Inactive | Your message delivery transactions are not boosted | | ... | Inactive | Your message delivery transactions are not boosted | -| 1000 | Expired | Your may submit a tx with the `deregister` call | +| 1000 | Expired | You may submit a tx with the `deregister` call | @@ -230,7 +230,7 @@ your relayer account. Then: - set the `bridgedChainId` to `bhpd`; -- check the both variants of the `owner` field: `ThisChain` is used to pay for message delivery transactions +- check both variants of the `owner` field: `ThisChain` is used to pay for message delivery transactions and `BridgedChain` is used to pay for message confirmation transactions. If check shows that you have some rewards, you can craft the claim transaction, with similar parameters. diff --git a/bridges/modules/grandpa/src/call_ext.rs b/bridges/modules/grandpa/src/call_ext.rs index 98fbeaa30bba..f08eb4c5d1ab 100644 --- a/bridges/modules/grandpa/src/call_ext.rs +++ b/bridges/modules/grandpa/src/call_ext.rs @@ -18,12 +18,8 @@ use crate::{ weights::WeightInfo, BestFinalized, BridgedBlockNumber, BridgedHeader, Config, CurrentAuthoritySet, Error, FreeHeadersRemaining, Pallet, }; -use bp_header_chain::{ - justification::GrandpaJustification, max_expected_submit_finality_proof_arguments_size, - ChainWithGrandpa, GrandpaConsensusLogReader, -}; +use bp_header_chain::{justification::GrandpaJustification, submit_finality_proof_limits_extras}; use bp_runtime::{BlockNumberOf, Chain, OwnedBridgeModule}; -use codec::Encode; use frame_support::{ dispatch::CallableCallFor, traits::{Get, IsSubType}, @@ -303,53 +299,31 @@ pub(crate) fn submit_finality_proof_info_from_args, I: 'static>( current_set_id: Option, is_free_execution_expected: bool, ) -> SubmitFinalityProofInfo> { - let block_number = *finality_target.number(); - - // the `submit_finality_proof` call will reject justifications with invalid, duplicate, - // unknown and extra signatures. It'll also reject justifications with less than necessary - // signatures. So we do not care about extra weight because of additional signatures here. - let precommits_len = justification.commit.precommits.len().saturated_into(); - let required_precommits = precommits_len; + // check if call exceeds limits. In other words - whether some size or weight is included + // in the call + let extras = + submit_finality_proof_limits_extras::(finality_target, justification); // We do care about extra weight because of more-than-expected headers in the votes // ancestries. But we have problems computing extra weight for additional headers (weight of // additional header is too small, so that our benchmarks aren't detecting that). So if there // are more than expected headers in votes ancestries, we will treat the whole call weight // as an extra weight. - let votes_ancestries_len = justification.votes_ancestries.len().saturated_into(); - let extra_weight = - if votes_ancestries_len > T::BridgedChain::REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY { - T::WeightInfo::submit_finality_proof(precommits_len, votes_ancestries_len) - } else { - Weight::zero() - }; - - // check if the `finality_target` is a mandatory header. If so, we are ready to refund larger - // size - let is_mandatory_finality_target = - GrandpaConsensusLogReader::>::find_scheduled_change( - finality_target.digest(), - ) - .is_some(); - - // we can estimate extra call size easily, without any additional significant overhead - let actual_call_size: u32 = finality_target - .encoded_size() - .saturating_add(justification.encoded_size()) - .saturated_into(); - let max_expected_call_size = max_expected_submit_finality_proof_arguments_size::( - is_mandatory_finality_target, - required_precommits, - ); - let extra_size = actual_call_size.saturating_sub(max_expected_call_size); + let extra_weight = if extras.is_weight_limit_exceeded { + let precommits_len = justification.commit.precommits.len().saturated_into(); + let votes_ancestries_len = justification.votes_ancestries.len().saturated_into(); + T::WeightInfo::submit_finality_proof(precommits_len, votes_ancestries_len) + } else { + Weight::zero() + }; SubmitFinalityProofInfo { - block_number, + block_number: *finality_target.number(), current_set_id, - is_mandatory: is_mandatory_finality_target, + is_mandatory: extras.is_mandatory_finality_target, is_free_execution_expected, extra_weight, - extra_size, + extra_size: extras.extra_size, } } diff --git a/bridges/primitives/header-chain/src/lib.rs b/bridges/primitives/header-chain/src/lib.rs index ad496012c6a3..af2afb65a26a 100644 --- a/bridges/primitives/header-chain/src/lib.rs +++ b/bridges/primitives/header-chain/src/lib.rs @@ -24,8 +24,8 @@ use crate::justification::{ GrandpaJustification, JustificationVerificationContext, JustificationVerificationError, }; use bp_runtime::{ - BasicOperatingMode, Chain, HashOf, HasherOf, HeaderOf, RawStorageProof, StorageProofChecker, - StorageProofError, UnderlyingChainProvider, + BasicOperatingMode, BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf, RawStorageProof, + StorageProofChecker, StorageProofError, UnderlyingChainProvider, }; use codec::{Codec, Decode, Encode, EncodeLike, MaxEncodedLen}; use core::{clone::Clone, cmp::Eq, default::Default, fmt::Debug}; @@ -35,7 +35,7 @@ use serde::{Deserialize, Serialize}; use sp_consensus_grandpa::{ AuthorityList, ConsensusLog, ScheduledChange, SetId, GRANDPA_ENGINE_ID, }; -use sp_runtime::{traits::Header as HeaderT, Digest, RuntimeDebug}; +use sp_runtime::{traits::Header as HeaderT, Digest, RuntimeDebug, SaturatedConversion}; use sp_std::{boxed::Box, vec::Vec}; pub mod justification; @@ -325,6 +325,68 @@ where const AVERAGE_HEADER_SIZE: u32 = ::AVERAGE_HEADER_SIZE; } +/// Result of checking maximal expected submit finality proof call weight and size. +#[derive(Debug)] +pub struct SubmitFinalityProofCallExtras { + /// If true, the call weight is larger than what we have assumed. + /// + /// We have some assumptions about headers and justifications of the bridged chain. + /// We know that if our assumptions are correct, then the call must not have the + /// weight above some limit. The fee paid for weight above that limit, is never refunded. + pub is_weight_limit_exceeded: bool, + /// Extra size (in bytes) that we assume are included in the call. + /// + /// We have some assumptions about headers and justifications of the bridged chain. + /// We know that if our assumptions are correct, then the call must not have the + /// weight above some limit. The fee paid for bytes above that limit, is never refunded. + pub extra_size: u32, + /// A flag that is true if the header is the mandatory header that enacts new + /// authorities set. + pub is_mandatory_finality_target: bool, +} + +/// Checks whether the given `header` and its finality `proof` fit the maximal expected +/// call limits (size and weight). The submission may be refunded sometimes (see pallet +/// configuration for details), but it should fit some limits. If the call has some extra +/// weight and/or size included, though, we won't refund it or refund will be partial. +pub fn submit_finality_proof_limits_extras( + header: &C::Header, + proof: &justification::GrandpaJustification, +) -> SubmitFinalityProofCallExtras { + // the `submit_finality_proof` call will reject justifications with invalid, duplicate, + // unknown and extra signatures. It'll also reject justifications with less than necessary + // signatures. So we do not care about extra weight because of additional signatures here. + let precommits_len = proof.commit.precommits.len().saturated_into(); + let required_precommits = precommits_len; + + // the weight check is simple - we assume that there are no more than the `limit` + // headers in the ancestry proof + let votes_ancestries_len: u32 = proof.votes_ancestries.len().saturated_into(); + let is_weight_limit_exceeded = + votes_ancestries_len > C::REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY; + + // check if the `finality_target` is a mandatory header. If so, we are ready to refund larger + // size + let is_mandatory_finality_target = + GrandpaConsensusLogReader::>::find_scheduled_change(header.digest()) + .is_some(); + + // we can estimate extra call size easily, without any additional significant overhead + let actual_call_size: u32 = + header.encoded_size().saturating_add(proof.encoded_size()).saturated_into(); + let max_expected_call_size = max_expected_submit_finality_proof_arguments_size::( + is_mandatory_finality_target, + required_precommits, + ); + let extra_size = actual_call_size.saturating_sub(max_expected_call_size); + + SubmitFinalityProofCallExtras { + is_weight_limit_exceeded, + extra_size, + is_mandatory_finality_target, + } +} + /// Returns maximal expected size of `submit_finality_proof` call arguments. pub fn max_expected_submit_finality_proof_arguments_size( is_mandatory_finality_target: bool, diff --git a/bridges/relays/client-substrate/src/error.rs b/bridges/relays/client-substrate/src/error.rs index 0b4466818188..2133c1888784 100644 --- a/bridges/relays/client-substrate/src/error.rs +++ b/bridges/relays/client-substrate/src/error.rs @@ -17,6 +17,7 @@ //! Substrate node RPC errors. use crate::SimpleRuntimeVersion; +use bp_header_chain::SubmitFinalityProofCallExtras; use bp_polkadot_core::parachains::ParaId; use jsonrpsee::core::ClientError as RpcError; use relay_utils::MaybeConnectionError; @@ -129,6 +130,12 @@ pub enum Error { /// Actual runtime version. actual: SimpleRuntimeVersion, }, + /// Finality proof submission exceeds size and/or weight limits. + #[error("Finality proof submission exceeds limits: {extras:?}")] + FinalityProofWeightLimitExceeded { + /// Finality proof submission extras. + extras: SubmitFinalityProofCallExtras, + }, /// Custom logic error. #[error("{0}")] Custom(String), diff --git a/bridges/relays/lib-substrate-relay/src/cli/relay_messages.rs b/bridges/relays/lib-substrate-relay/src/cli/relay_messages.rs index e5b07b241581..943feba072e4 100644 --- a/bridges/relays/lib-substrate-relay/src/cli/relay_messages.rs +++ b/bridges/relays/lib-substrate-relay/src/cli/relay_messages.rs @@ -80,6 +80,24 @@ pub struct RelayMessagesRangeParams { target_sign: TargetSigningParams, } +/// Messages delivery confirmation relaying params. +#[derive(StructOpt)] +pub struct RelayMessagesDeliveryConfirmationParams { + /// Number of the target chain header that we will use to prepare a messages + /// delivery proof. This header must be previously proved to the source chain. + #[structopt(long)] + at_target_block: u128, + /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. + #[structopt(long, default_value = "00000000")] + lane: HexLaneId, + #[structopt(flatten)] + source: SourceConnectionParams, + #[structopt(flatten)] + source_sign: SourceSigningParams, + #[structopt(flatten)] + target: TargetConnectionParams, +} + /// Trait used for relaying messages between 2 chains. #[async_trait] pub trait MessagesRelayer: MessagesCliBridge @@ -154,4 +172,37 @@ where ) .await } + + /// Relay a messages delivery confirmation. + async fn relay_messages_delivery_confirmation( + data: RelayMessagesDeliveryConfirmationParams, + ) -> anyhow::Result<()> { + let source_client = data.source.into_client::().await?; + let target_client = data.target.into_client::().await?; + let source_sign = data.source_sign.to_keypair::()?; + let source_transactions_mortality = data.source_sign.transactions_mortality()?; + + let at_target_block = target_client + .header_by_number(data.at_target_block.unique_saturated_into()) + .await + .map_err(|e| { + log::trace!( + target: "bridge", + "Failed to read {} header with number {}: {e:?}", + Self::Target::NAME, + data.at_target_block, + ); + anyhow::format_err!("The command has failed") + })? + .id(); + + crate::messages_lane::relay_messages_delivery_confirmation::( + source_client, + target_client, + TransactionParams { signer: source_sign, mortality: source_transactions_mortality }, + at_target_block, + data.lane.into(), + ) + .await + } } diff --git a/bridges/relays/lib-substrate-relay/src/finality/target.rs b/bridges/relays/lib-substrate-relay/src/finality/target.rs index 0874fa53549c..52ab2462c62c 100644 --- a/bridges/relays/lib-substrate-relay/src/finality/target.rs +++ b/bridges/relays/lib-substrate-relay/src/finality/target.rs @@ -137,6 +137,16 @@ impl TargetClient: Send { @@ -129,12 +115,11 @@ pub trait Engine: Send { ) -> Result; /// Checks whether the given `header` and its finality `proof` fit the maximal expected - /// call size limit. If result is `MaxExpectedCallSizeCheck::Exceeds { .. }`, this - /// submission won't be fully refunded and relayer will spend its own funds on that. - fn check_max_expected_call_size( + /// call limits (size and weight). + fn check_max_expected_call_limits( header: &C::Header, proof: &Self::FinalityProof, - ) -> MaxExpectedCallSizeCheck; + ) -> SubmitFinalityProofCallExtras; /// Prepare initialization data for the finality bridge pallet. async fn prepare_initialization_data( @@ -245,22 +230,11 @@ impl Engine for Grandpa { }) } - fn check_max_expected_call_size( + fn check_max_expected_call_limits( header: &C::Header, proof: &Self::FinalityProof, - ) -> MaxExpectedCallSizeCheck { - let is_mandatory = Self::ConsensusLogReader::schedules_authorities_change(header.digest()); - let call_size: u32 = - header.encoded_size().saturating_add(proof.encoded_size()).saturated_into(); - let max_call_size = max_expected_submit_finality_proof_arguments_size::( - is_mandatory, - proof.commit.precommits.len().saturated_into(), - ); - if call_size > max_call_size { - MaxExpectedCallSizeCheck::Exceeds { call_size, max_call_size } - } else { - MaxExpectedCallSizeCheck::Ok - } + ) -> SubmitFinalityProofCallExtras { + bp_header_chain::submit_finality_proof_limits_extras::(header, proof) } /// Prepare initialization data for the GRANDPA verifier pallet. diff --git a/bridges/relays/lib-substrate-relay/src/messages_lane.rs b/bridges/relays/lib-substrate-relay/src/messages_lane.rs index a34b165289b2..08550d19bae0 100644 --- a/bridges/relays/lib-substrate-relay/src/messages_lane.rs +++ b/bridges/relays/lib-substrate-relay/src/messages_lane.rs @@ -262,7 +262,7 @@ where source_client, params.lane_id, relayer_id_at_source, - params.target_transaction_params, + Some(params.target_transaction_params), params.source_to_target_headers_relay, ), { @@ -307,7 +307,7 @@ where source_client, lane_id, relayer_id_at_source, - target_transaction_params, + Some(target_transaction_params), None, ), at_source_block, @@ -318,6 +318,44 @@ where .map_err(|_| anyhow::format_err!("The command has failed")) } +/// Relay messages delivery confirmation of Substrate-to-Substrate messages. +/// No checks are made to ensure that transaction will succeed. +pub async fn relay_messages_delivery_confirmation( + source_client: Client, + target_client: Client, + source_transaction_params: TransactionParams>, + at_target_block: HeaderIdOf, + lane_id: LaneId, +) -> anyhow::Result<()> +where + AccountIdOf: From< as Pair>::Public>, + AccountIdOf: From< as Pair>::Public>, + BalanceOf: TryFrom>, +{ + let relayer_id_at_source: AccountIdOf = + source_transaction_params.signer.public().into(); + messages_relay::relay_messages_delivery_confirmation( + SubstrateMessagesSource::

::new( + source_client.clone(), + target_client.clone(), + lane_id, + source_transaction_params, + None, + ), + SubstrateMessagesTarget::

::new( + target_client, + source_client, + lane_id, + relayer_id_at_source, + None, + None, + ), + at_target_block, + ) + .await + .map_err(|_| anyhow::format_err!("The command has failed")) +} + /// Different ways of building `receive_messages_proof` calls. pub trait ReceiveMessagesProofCallBuilder { /// Given messages proof, build call of `receive_messages_proof` function of bridge diff --git a/bridges/relays/lib-substrate-relay/src/messages_target.rs b/bridges/relays/lib-substrate-relay/src/messages_target.rs index 633b11f0b802..5ffb2b6c771e 100644 --- a/bridges/relays/lib-substrate-relay/src/messages_target.rs +++ b/bridges/relays/lib-substrate-relay/src/messages_target.rs @@ -40,8 +40,8 @@ use messages_relay::{ message_lane_loop::{NoncesSubmitArtifacts, TargetClient, TargetClientState}, }; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, BalanceOf, CallOf, Client, Error as SubstrateError, HashOf, - TransactionEra, TransactionTracker, UnsignedTransaction, + AccountIdOf, AccountKeyPairOf, BalanceOf, CallOf, Chain, Client, Error as SubstrateError, + HashOf, TransactionEra, TransactionTracker, UnsignedTransaction, }; use relay_utils::relay_loop::Client as RelayClient; use sp_core::Pair; @@ -57,7 +57,7 @@ pub struct SubstrateMessagesTarget { source_client: Client, lane_id: LaneId, relayer_id_at_source: AccountIdOf, - transaction_params: TransactionParams>, + transaction_params: Option>>, source_to_target_headers_relay: Option>>, } @@ -68,7 +68,7 @@ impl SubstrateMessagesTarget

{ source_client: Client, lane_id: LaneId, relayer_id_at_source: AccountIdOf, - transaction_params: TransactionParams>, + transaction_params: Option>>, source_to_target_headers_relay: Option< Arc>, >, @@ -249,11 +249,18 @@ where None => messages_proof_call, }; - let transaction_params = self.transaction_params.clone(); + let transaction_params = self.transaction_params.clone().map(Ok).unwrap_or_else(|| { + // this error shall never happen in practice, so it not deserves + // a separate error variant + Err(SubstrateError::Custom(format!( + "Cannot sign transaction of {} chain", + P::TargetChain::NAME, + ))) + })?; let tx_tracker = self .target_client .submit_and_watch_signed_extrinsic( - &self.transaction_params.signer, + &transaction_params.signer, move |best_block_id, transaction_nonce| { Ok(UnsignedTransaction::new(final_call.into(), transaction_nonce) .era(TransactionEra::new(best_block_id, transaction_params.mortality))) diff --git a/bridges/relays/lib-substrate-relay/src/on_demand/headers.rs b/bridges/relays/lib-substrate-relay/src/on_demand/headers.rs index 74f3a70c5e81..202f53ea4e4f 100644 --- a/bridges/relays/lib-substrate-relay/src/on_demand/headers.rs +++ b/bridges/relays/lib-substrate-relay/src/on_demand/headers.rs @@ -16,9 +16,7 @@ //! On-demand Substrate -> Substrate header finality relay. -use crate::{ - finality::SubmitFinalityProofCallBuilder, finality_base::engine::MaxExpectedCallSizeCheck, -}; +use crate::finality::SubmitFinalityProofCallBuilder; use async_std::sync::{Arc, Mutex}; use async_trait::async_trait; @@ -156,22 +154,21 @@ impl OnDemandRelay( .await } +/// Relay messages delivery confirmation. +pub async fn relay_messages_delivery_confirmation( + source_client: impl MessageLaneSourceClient

, + target_client: impl MessageLaneTargetClient

, + at: TargetHeaderIdOf

, +) -> Result<(), ()> { + // prepare messages delivery proof + let (at, proof) = target_client.prove_messages_receiving(at.clone()).await.map_err(|e| { + log::error!( + target: "bridge", + "Failed to generate messages delivery proof at {:?}: {:?}", + at, + e, + ); + })?; + // submit messages delivery proof to the source node + let tx_tracker = + source_client + .submit_messages_receiving_proof(None, at, proof) + .await + .map_err(|e| { + log::error!( + target: "bridge", + "Failed to submit messages delivery proof: {:?}", + e, + ); + })?; + + match tx_tracker.wait().await { + TrackedTransactionStatus::Finalized(_) => Ok(()), + TrackedTransactionStatus::Lost => { + log::error!("Transaction with messages delivery proof is considered lost"); + Err(()) + }, + } +} + /// Messages receiving confirmations race. struct ReceivingConfirmationsRace

(std::marker::PhantomData

); diff --git a/cumulus/pallets/xcmp-queue/src/mock.rs b/cumulus/pallets/xcmp-queue/src/mock.rs index dd87e07c33f2..e166a78ee822 100644 --- a/cumulus/pallets/xcmp-queue/src/mock.rs +++ b/cumulus/pallets/xcmp-queue/src/mock.rs @@ -321,10 +321,13 @@ impl GetChannelInfo for MockedChannelInfo { pub(crate) fn mk_page() -> Vec { let mut page = Vec::::new(); + let newer_xcm_version = xcm::prelude::XCM_VERSION; + let older_xcm_version = newer_xcm_version - 1; + for i in 0..100 { page.extend(match i % 2 { - 0 => v2_xcm().encode(), - 1 => v3_xcm().encode(), + 0 => versioned_xcm(older_xcm_version).encode(), + 1 => versioned_xcm(newer_xcm_version).encode(), // We cannot push an undecodable XCM here since it would break the decode stream. // This is expected and the whole reason to introduce `MaybeDoubleEncodedVersionedXcm` // instead. @@ -335,12 +338,9 @@ pub(crate) fn mk_page() -> Vec { page } -pub(crate) fn v2_xcm() -> VersionedXcm<()> { - let instr = xcm::v2::Instruction::<()>::ClearOrigin; - VersionedXcm::V2(xcm::v2::Xcm::<()>(vec![instr; 3])) -} - -pub(crate) fn v3_xcm() -> VersionedXcm<()> { - let instr = xcm::v3::Instruction::<()>::Trap(1); - VersionedXcm::V3(xcm::v3::Xcm::<()>(vec![instr; 3])) +pub(crate) fn versioned_xcm(version: XcmVersion) -> VersionedXcm<()> { + let instr = Instruction::<()>::Trap(1); + VersionedXcm::from(Xcm::<()>(vec![instr; 3])) + .into_version(version) + .expect("Version conversion should work") } diff --git a/cumulus/pallets/xcmp-queue/src/tests.rs b/cumulus/pallets/xcmp-queue/src/tests.rs index 7c02059e5a90..cdf41e27f0b2 100644 --- a/cumulus/pallets/xcmp-queue/src/tests.rs +++ b/cumulus/pallets/xcmp-queue/src/tests.rs @@ -14,7 +14,7 @@ // limitations under the License. use super::{ - mock::{mk_page, v2_xcm, v3_xcm, EnqueuedMessages, HRMP_PARA_ID}, + mock::{mk_page, versioned_xcm, EnqueuedMessages, HRMP_PARA_ID}, *, }; use XcmpMessageFormat::*; @@ -536,8 +536,8 @@ fn hrmp_signals_are_prioritized() { #[test] fn maybe_double_encoded_versioned_xcm_works() { // pre conditions - assert_eq!(VersionedXcm::<()>::V2(Default::default()).encode(), &[2, 0]); assert_eq!(VersionedXcm::<()>::V3(Default::default()).encode(), &[3, 0]); + assert_eq!(VersionedXcm::<()>::V4(Default::default()).encode(), &[4, 0]); } // Now also testing a page instead of just concat messages. @@ -545,15 +545,18 @@ fn maybe_double_encoded_versioned_xcm_works() { fn maybe_double_encoded_versioned_xcm_decode_page_works() { let page = mk_page(); + let newer_xcm_version = xcm::prelude::XCM_VERSION; + let older_xcm_version = newer_xcm_version - 1; + // Now try to decode the page. let input = &mut &page[..]; for i in 0..100 { match (i % 2, VersionedXcm::<()>::decode(input)) { (0, Ok(xcm)) => { - assert_eq!(xcm, v2_xcm()); + assert_eq!(xcm, versioned_xcm(older_xcm_version)); }, (1, Ok(xcm)) => { - assert_eq!(xcm, v3_xcm()); + assert_eq!(xcm, versioned_xcm(newer_xcm_version)); }, unexpected => unreachable!("{:?}", unexpected), } @@ -568,14 +571,17 @@ fn take_first_concatenated_xcm_works() { let page = mk_page(); let input = &mut &page[..]; + let newer_xcm_version = xcm::prelude::XCM_VERSION; + let older_xcm_version = newer_xcm_version - 1; + for i in 0..100 { let xcm = XcmpQueue::take_first_concatenated_xcm(input, &mut WeightMeter::new()).unwrap(); match (i % 2, xcm) { (0, data) | (2, data) => { - assert_eq!(data, v2_xcm().encode()); + assert_eq!(data, versioned_xcm(older_xcm_version).encode()); }, (1, data) | (3, data) => { - assert_eq!(data, v3_xcm().encode()); + assert_eq!(data, versioned_xcm(newer_xcm_version).encode()); }, unexpected => unreachable!("{:?}", unexpected), } diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/send_xcm.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/send_xcm.rs index a1d871cdb618..78788634e6ff 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/send_xcm.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/send_xcm.rs @@ -61,10 +61,13 @@ fn send_xcm_from_rococo_relay_to_westend_asset_hub_should_fail_on_not_applicable #[test] fn send_xcm_through_opened_lane_with_different_xcm_version_on_hops_works() { // Initially set only default version on all runtimes - AssetHubRococo::force_default_xcm_version(Some(xcm::v2::prelude::XCM_VERSION)); - BridgeHubRococo::force_default_xcm_version(Some(xcm::v2::prelude::XCM_VERSION)); - BridgeHubWestend::force_default_xcm_version(Some(xcm::v2::prelude::XCM_VERSION)); - AssetHubWestend::force_default_xcm_version(Some(xcm::v2::prelude::XCM_VERSION)); + let newer_xcm_version = xcm::prelude::XCM_VERSION; + let older_xcm_version = newer_xcm_version - 1; + + AssetHubRococo::force_default_xcm_version(Some(older_xcm_version)); + BridgeHubRococo::force_default_xcm_version(Some(older_xcm_version)); + BridgeHubWestend::force_default_xcm_version(Some(older_xcm_version)); + AssetHubWestend::force_default_xcm_version(Some(older_xcm_version)); // prepare data let destination = asset_hub_westend_location(); @@ -87,42 +90,12 @@ fn send_xcm_through_opened_lane_with_different_xcm_version_on_hops_works() { ); // set destination version - AssetHubRococo::force_xcm_version(destination.clone(), xcm::v3::prelude::XCM_VERSION); - - // TODO: remove this block, when removing `xcm:v2` - { - // send XCM from AssetHubRococo - fails - AssetHubRococo is set to the default/safe `2` - // version, which does not have the `ExportMessage` instruction. If the default `2` is - // changed to `3`, then this assert can go away" - assert_err!( - send_asset_from_asset_hub_rococo(destination.clone(), (native_token.clone(), amount)), - DispatchError::Module(sp_runtime::ModuleError { - index: 31, - error: [1, 0, 0, 0], - message: Some("SendFailure") - }) - ); - - // set exact version for BridgeHubWestend to `2` without `ExportMessage` instruction - AssetHubRococo::force_xcm_version( - ParentThen(Parachain(BridgeHubRococo::para_id().into()).into()).into(), - xcm::v2::prelude::XCM_VERSION, - ); - // send XCM from AssetHubRococo - fails - `ExportMessage` is not in `2` - assert_err!( - send_asset_from_asset_hub_rococo(destination.clone(), (native_token.clone(), amount)), - DispatchError::Module(sp_runtime::ModuleError { - index: 31, - error: [1, 0, 0, 0], - message: Some("SendFailure") - }) - ); - } + AssetHubRococo::force_xcm_version(destination.clone(), newer_xcm_version); // set version with `ExportMessage` for BridgeHubRococo AssetHubRococo::force_xcm_version( ParentThen(Parachain(BridgeHubRococo::para_id().into()).into()).into(), - xcm::v3::prelude::XCM_VERSION, + newer_xcm_version, ); // send XCM from AssetHubRococo - ok assert_ok!(send_asset_from_asset_hub_rococo( @@ -134,14 +107,11 @@ fn send_xcm_through_opened_lane_with_different_xcm_version_on_hops_works() { assert_bridge_hub_rococo_message_accepted(false); // set version for remote BridgeHub on BridgeHubRococo - BridgeHubRococo::force_xcm_version( - bridge_hub_westend_location(), - xcm::v3::prelude::XCM_VERSION, - ); + BridgeHubRococo::force_xcm_version(bridge_hub_westend_location(), newer_xcm_version); // set version for AssetHubWestend on BridgeHubWestend BridgeHubWestend::force_xcm_version( ParentThen(Parachain(AssetHubWestend::para_id().into()).into()).into(), - xcm::v3::prelude::XCM_VERSION, + newer_xcm_version, ); // send XCM from AssetHubRococo - ok @@ -164,20 +134,4 @@ fn send_xcm_through_opened_lane_with_different_xcm_version_on_hops_works() { ] ); }); - - // TODO: remove this block, when removing `xcm:v2` - { - // set `2` version for remote BridgeHub on BridgeHubRococo, which does not have - // `UniversalOrigin` and `DescendOrigin` - BridgeHubRococo::force_xcm_version( - bridge_hub_westend_location(), - xcm::v2::prelude::XCM_VERSION, - ); - - // send XCM from AssetHubRococo - ok - assert_ok!(send_asset_from_asset_hub_rococo(destination, (native_token, amount))); - // message is not accepted on the local BridgeHub (`DestinationUnsupported`) because we - // cannot add `UniversalOrigin` and `DescendOrigin` - assert_bridge_hub_rococo_message_accepted(false); - } } diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/send_xcm.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/send_xcm.rs index b01be5e8dc84..8539df97be93 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/send_xcm.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/send_xcm.rs @@ -61,10 +61,13 @@ fn send_xcm_from_westend_relay_to_rococo_asset_hub_should_fail_on_not_applicable #[test] fn send_xcm_through_opened_lane_with_different_xcm_version_on_hops_works() { // Initially set only default version on all runtimes - AssetHubRococo::force_default_xcm_version(Some(xcm::v2::prelude::XCM_VERSION)); - BridgeHubRococo::force_default_xcm_version(Some(xcm::v2::prelude::XCM_VERSION)); - BridgeHubWestend::force_default_xcm_version(Some(xcm::v2::prelude::XCM_VERSION)); - AssetHubWestend::force_default_xcm_version(Some(xcm::v2::prelude::XCM_VERSION)); + let newer_xcm_version = xcm::prelude::XCM_VERSION; + let older_xcm_version = newer_xcm_version - 1; + + AssetHubRococo::force_default_xcm_version(Some(older_xcm_version)); + BridgeHubRococo::force_default_xcm_version(Some(older_xcm_version)); + BridgeHubWestend::force_default_xcm_version(Some(older_xcm_version)); + AssetHubWestend::force_default_xcm_version(Some(older_xcm_version)); // prepare data let destination = asset_hub_rococo_location(); @@ -87,42 +90,12 @@ fn send_xcm_through_opened_lane_with_different_xcm_version_on_hops_works() { ); // set destination version - AssetHubWestend::force_xcm_version(destination.clone(), xcm::v3::prelude::XCM_VERSION); - - // TODO: remove this block, when removing `xcm:v2` - { - // send XCM from AssetHubRococo - fails - AssetHubRococo is set to the default/safe `2` - // version, which does not have the `ExportMessage` instruction. If the default `2` is - // changed to `3`, then this assert can go away" - assert_err!( - send_asset_from_asset_hub_westend(destination.clone(), (native_token.clone(), amount)), - DispatchError::Module(sp_runtime::ModuleError { - index: 31, - error: [1, 0, 0, 0], - message: Some("SendFailure") - }) - ); - - // set exact version for BridgeHubWestend to `2` without `ExportMessage` instruction - AssetHubWestend::force_xcm_version( - ParentThen(Parachain(BridgeHubWestend::para_id().into()).into()).into(), - xcm::v2::prelude::XCM_VERSION, - ); - // send XCM from AssetHubWestend - fails - `ExportMessage` is not in `2` - assert_err!( - send_asset_from_asset_hub_westend(destination.clone(), (native_token.clone(), amount)), - DispatchError::Module(sp_runtime::ModuleError { - index: 31, - error: [1, 0, 0, 0], - message: Some("SendFailure") - }) - ); - } + AssetHubWestend::force_xcm_version(destination.clone(), newer_xcm_version); // set version with `ExportMessage` for BridgeHubWestend AssetHubWestend::force_xcm_version( ParentThen(Parachain(BridgeHubWestend::para_id().into()).into()).into(), - xcm::v3::prelude::XCM_VERSION, + newer_xcm_version, ); // send XCM from AssetHubWestend - ok assert_ok!(send_asset_from_asset_hub_westend( @@ -134,14 +107,11 @@ fn send_xcm_through_opened_lane_with_different_xcm_version_on_hops_works() { assert_bridge_hub_westend_message_accepted(false); // set version for remote BridgeHub on BridgeHubWestend - BridgeHubWestend::force_xcm_version( - bridge_hub_rococo_location(), - xcm::v3::prelude::XCM_VERSION, - ); + BridgeHubWestend::force_xcm_version(bridge_hub_rococo_location(), newer_xcm_version); // set version for AssetHubRococo on BridgeHubRococo BridgeHubRococo::force_xcm_version( ParentThen(Parachain(AssetHubRococo::para_id().into()).into()).into(), - xcm::v3::prelude::XCM_VERSION, + newer_xcm_version, ); // send XCM from AssetHubWestend - ok @@ -164,20 +134,4 @@ fn send_xcm_through_opened_lane_with_different_xcm_version_on_hops_works() { ] ); }); - - // TODO: remove this block, when removing `xcm:v2` - { - // set `2` version for remote BridgeHub on BridgeHubRococo, which does not have - // `UniversalOrigin` and `DescendOrigin` - BridgeHubWestend::force_xcm_version( - bridge_hub_rococo_location(), - xcm::v2::prelude::XCM_VERSION, - ); - - // send XCM from AssetHubWestend - ok - assert_ok!(send_asset_from_asset_hub_westend(destination, (native_token, amount))); - // message is not accepted on the local BridgeHub (`DestinationUnsupported`) because we - // cannot add `UniversalOrigin` and `DescendOrigin` - assert_bridge_hub_westend_message_accepted(false); - } } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 25c66afc8a53..4705d12e60c8 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -93,8 +93,8 @@ use pallet_xcm::{EnsureXcm, IsVoiceOfBody}; use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate}; #[cfg(feature = "runtime-benchmarks")] use xcm::latest::prelude::{ - Asset, Fungible, Here, InteriorLocation, Junction, Junction::*, Location, NetworkId, - NonFungible, Parent, ParentThen, Response, XCM_VERSION, + Asset, Assets as XcmAssets, Fungible, Here, InteriorLocation, Junction, Junction::*, Location, + NetworkId, NonFungible, Parent, ParentThen, Response, XCM_VERSION, }; use xcm::{ latest::prelude::{AssetId, BodyId}, @@ -1535,7 +1535,7 @@ impl_runtime_apis! { } fn set_up_complex_asset_transfer( - ) -> Option<(xcm::v4::Assets, u32, Location, Box)> { + ) -> Option<(XcmAssets, u32, Location, Box)> { // Transfer to Relay some local AH asset (local-reserve-transfer) while paying // fees using teleported native token. // (We don't care that Relay doesn't accept incoming unknown AH local asset) @@ -1566,7 +1566,7 @@ impl_runtime_apis! { ); let transfer_asset: Asset = (asset_location, asset_amount).into(); - let assets: xcm::v4::Assets = vec![fee_asset.clone(), transfer_asset].into(); + let assets: XcmAssets = vec![fee_asset.clone(), transfer_asset].into(); let fee_index = if assets.get(0).unwrap().eq(&fee_asset) { 0 } else { 1 }; // verify transferred successfully @@ -1634,7 +1634,7 @@ impl_runtime_apis! { fn valid_destination() -> Result { Ok(TokenLocation::get()) } - fn worst_case_holding(depositable_count: u32) -> xcm::v4::Assets { + fn worst_case_holding(depositable_count: u32) -> XcmAssets { // A mix of fungible, non-fungible, and concrete assets. let holding_non_fungibles = MaxAssetsIntoHolding::get() / 2 - depositable_count; let holding_fungibles = holding_non_fungibles.saturating_sub(2); // -2 for two `iter::once` bellow @@ -1695,7 +1695,7 @@ impl_runtime_apis! { (0u64, Response::Version(Default::default())) } - fn worst_case_asset_exchange() -> Result<(xcm::v4::Assets, xcm::v4::Assets), BenchmarkError> { + fn worst_case_asset_exchange() -> Result<(XcmAssets, XcmAssets), BenchmarkError> { Err(BenchmarkError::Skip) } @@ -1714,9 +1714,9 @@ impl_runtime_apis! { Ok(TokenLocation::get()) } - fn claimable_asset() -> Result<(Location, Location, xcm::v4::Assets), BenchmarkError> { + fn claimable_asset() -> Result<(Location, Location, XcmAssets), BenchmarkError> { let origin = TokenLocation::get(); - let assets: xcm::v4::Assets = (TokenLocation::get(), 1_000 * UNITS).into(); + let assets: XcmAssets = (TokenLocation::get(), 1_000 * UNITS).into(); let ticket = Location { parents: 0, interior: Here }; Ok((origin, ticket, assets)) } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index c8d388df16c0..a82094d6f8a6 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -95,8 +95,8 @@ use xcm::latest::prelude::AssetId; #[cfg(feature = "runtime-benchmarks")] use xcm::latest::prelude::{ - Asset, Fungible, Here, InteriorLocation, Junction, Junction::*, Location, NetworkId, - NonFungible, Parent, ParentThen, Response, XCM_VERSION, + Asset, Assets as XcmAssets, Fungible, Here, InteriorLocation, Junction, Junction::*, Location, + NetworkId, NonFungible, Parent, ParentThen, Response, XCM_VERSION, }; use xcm_fee_payment_runtime_api::{ @@ -1629,7 +1629,7 @@ impl_runtime_apis! { } fn set_up_complex_asset_transfer( - ) -> Option<(xcm::v4::Assets, u32, Location, Box)> { + ) -> Option<(XcmAssets, u32, Location, Box)> { // Transfer to Relay some local AH asset (local-reserve-transfer) while paying // fees using teleported native token. // (We don't care that Relay doesn't accept incoming unknown AH local asset) @@ -1660,7 +1660,7 @@ impl_runtime_apis! { ); let transfer_asset: Asset = (asset_location, asset_amount).into(); - let assets: xcm::v4::Assets = vec![fee_asset.clone(), transfer_asset].into(); + let assets: XcmAssets = vec![fee_asset.clone(), transfer_asset].into(); let fee_index = if assets.get(0).unwrap().eq(&fee_asset) { 0 } else { 1 }; // verify transferred successfully @@ -1733,7 +1733,7 @@ impl_runtime_apis! { fn valid_destination() -> Result { Ok(WestendLocation::get()) } - fn worst_case_holding(depositable_count: u32) -> xcm::v4::Assets { + fn worst_case_holding(depositable_count: u32) -> XcmAssets { // A mix of fungible, non-fungible, and concrete assets. let holding_non_fungibles = MaxAssetsIntoHolding::get() / 2 - depositable_count; let holding_fungibles = holding_non_fungibles - 2; // -2 for two `iter::once` bellow @@ -1794,7 +1794,7 @@ impl_runtime_apis! { (0u64, Response::Version(Default::default())) } - fn worst_case_asset_exchange() -> Result<(xcm::v4::Assets, xcm::v4::Assets), BenchmarkError> { + fn worst_case_asset_exchange() -> Result<(XcmAssets, XcmAssets), BenchmarkError> { Err(BenchmarkError::Skip) } @@ -1813,9 +1813,9 @@ impl_runtime_apis! { Ok(WestendLocation::get()) } - fn claimable_asset() -> Result<(Location, Location, xcm::v4::Assets), BenchmarkError> { + fn claimable_asset() -> Result<(Location, Location, XcmAssets), BenchmarkError> { let origin = WestendLocation::get(); - let assets: xcm::v4::Assets = (AssetId(WestendLocation::get()), 1_000 * UNITS).into(); + let assets: XcmAssets = (AssetId(WestendLocation::get()), 1_000 * UNITS).into(); let ticket = Location { parents: 0, interior: Here }; Ok((origin, ticket, assets)) } diff --git a/docs/RELEASE.md b/docs/RELEASE.md index e73be2779a99..653e6a2a3e92 100644 --- a/docs/RELEASE.md +++ b/docs/RELEASE.md @@ -45,7 +45,7 @@ variable. ## Westend & Rococo -For the these networks, in addition to incrementing the `Cargo.toml` version we also increment the `spec_version` and +For these networks, in addition to incrementing the `Cargo.toml` version we also increment the `spec_version` and sometimes the `transaction_version`. The spec version is also following the node version. Its schema is: `M_mmm_ppp` and for example `1_002_000` is the node release `1.2.0`. This versioning has no further meaning, and is only done to map from an on chain `spec_version` easily to the release in this repository. diff --git a/polkadot/roadmap/implementers-guide/src/runtime/scheduler.md b/polkadot/roadmap/implementers-guide/src/runtime/scheduler.md index 083ed2b6feac..be1e71666ad2 100644 --- a/polkadot/roadmap/implementers-guide/src/runtime/scheduler.md +++ b/polkadot/roadmap/implementers-guide/src/runtime/scheduler.md @@ -1,7 +1,7 @@ # Scheduler Pallet > TODO: this section is still heavily under construction. key questions about availability cores and validator -> assignment are still open and the flow of the the section may be contradictory or inconsistent +> assignment are still open and the flow of the section may be contradictory or inconsistent The Scheduler module is responsible for two main tasks: diff --git a/polkadot/xcm/pallet-xcm/src/benchmarking.rs b/polkadot/xcm/pallet-xcm/src/benchmarking.rs index 081a4235b779..da46a6a37c06 100644 --- a/polkadot/xcm/pallet-xcm/src/benchmarking.rs +++ b/polkadot/xcm/pallet-xcm/src/benchmarking.rs @@ -15,12 +15,11 @@ // along with Polkadot. If not, see . use super::*; -use bounded_collections::{ConstU32, WeakBoundedVec}; use frame_benchmarking::{benchmarks, whitelisted_caller, BenchmarkError, BenchmarkResult}; use frame_support::{assert_ok, weights::Weight}; use frame_system::RawOrigin; use sp_std::prelude::*; -use xcm::{latest::prelude::*, v2}; +use xcm::latest::prelude::*; use xcm_builder::EnsureDelivery; use xcm_executor::traits::FeeReason; @@ -313,15 +312,17 @@ benchmarks! { } notify_target_migration_fail { - let bad_loc: v2::MultiLocation = v2::Junction::Plurality { - id: v2::BodyId::Named(WeakBoundedVec::>::try_from(vec![0; 32]) - .expect("vec has a length of 32 bits; qed")), - part: v2::BodyPart::Voice, - } - .into(); - let bad_loc = VersionedLocation::from(bad_loc); + let newer_xcm_version = xcm::prelude::XCM_VERSION; + let older_xcm_version = newer_xcm_version - 1; + let bad_location: Location = Plurality { + id: BodyId::Unit, + part: BodyPart::Voice, + }.into(); + let bad_location = VersionedLocation::from(bad_location) + .into_version(older_xcm_version) + .expect("Version convertion should work"); let current_version = T::AdvertisedXcmVersion::get(); - VersionNotifyTargets::::insert(current_version, bad_loc, (0, Weight::zero(), current_version)); + VersionNotifyTargets::::insert(current_version, bad_location, (0, Weight::zero(), current_version)); }: { crate::Pallet::::check_xcm_version_change(VersionMigrationStage::MigrateAndNotifyOldTargets, Weight::zero()); } diff --git a/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs b/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs index f42e220d6932..af81ac9cf43a 100644 --- a/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs +++ b/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs @@ -76,7 +76,7 @@ fn limited_teleport_assets_works() { )] ); let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1); - let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap(); + let _check_v3_ok: xcm::v3::Xcm<()> = versioned_sent.try_into().unwrap(); let mut last_events = last_events(3).into_iter(); assert_eq!( diff --git a/polkadot/xcm/pallet-xcm/src/tests/mod.rs b/polkadot/xcm/pallet-xcm/src/tests/mod.rs index 02aeafd68e83..c16c1a1ba986 100644 --- a/polkadot/xcm/pallet-xcm/src/tests/mod.rs +++ b/polkadot/xcm/pallet-xcm/src/tests/mod.rs @@ -602,11 +602,11 @@ fn basic_subscription_works() { let weight = BaseXcmWeight::get(); let mut message = Xcm::<()>(vec![ - // Remote supports XCM v2 + // Remote supports XCM v3 QueryResponse { query_id: 0, max_weight: Weight::zero(), - response: Response::Version(1), + response: Response::Version(3), querier: None, }, ]); @@ -764,14 +764,14 @@ fn subscription_side_upgrades_work_with_notify() { new_test_ext_with_balances(vec![]).execute_with(|| { AdvertisedXcmVersion::set(1); - // An entry from a previous runtime with v2 XCM. - let v2_location = VersionedLocation::V2(xcm::v2::Junction::Parachain(1001).into()); - VersionNotifyTargets::::insert(1, v2_location, (70, Weight::zero(), 2)); - let v3_location = Parachain(1003).into_versioned(); - VersionNotifyTargets::::insert(3, v3_location, (72, Weight::zero(), 2)); + // An entry from a previous runtime with v3 XCM. + let v3_location = VersionedLocation::V3(xcm::v3::Junction::Parachain(1001).into()); + VersionNotifyTargets::::insert(3, v3_location, (70, Weight::zero(), 3)); + let v4_location = Parachain(1003).into_versioned(); + VersionNotifyTargets::::insert(4, v4_location, (72, Weight::zero(), 3)); // New version. - AdvertisedXcmVersion::set(3); + AdvertisedXcmVersion::set(4); // A runtime upgrade which alters the version does send notifications. CurrentMigration::::put(VersionMigrationStage::default()); @@ -780,13 +780,13 @@ fn subscription_side_upgrades_work_with_notify() { let instr1 = QueryResponse { query_id: 70, max_weight: Weight::zero(), - response: Response::Version(3), + response: Response::Version(4), querier: None, }; let instr3 = QueryResponse { query_id: 72, max_weight: Weight::zero(), - response: Response::Version(3), + response: Response::Version(4), querier: None, }; let mut sent = take_sent_xcm(); @@ -807,8 +807,8 @@ fn subscription_side_upgrades_work_with_notify() { assert_eq!( contents, vec![ - (XCM_VERSION, Parachain(1001).into_versioned(), (70, Weight::zero(), 3)), - (XCM_VERSION, Parachain(1003).into_versioned(), (72, Weight::zero(), 3)), + (XCM_VERSION, Parachain(1001).into_versioned(), (70, Weight::zero(), 4)), + (XCM_VERSION, Parachain(1003).into_versioned(), (72, Weight::zero(), 4)), ] ); }); @@ -817,11 +817,11 @@ fn subscription_side_upgrades_work_with_notify() { #[test] fn subscription_side_upgrades_work_without_notify() { new_test_ext_with_balances(vec![]).execute_with(|| { - // An entry from a previous runtime with v2 XCM. - let v2_location = VersionedLocation::V2(xcm::v2::Junction::Parachain(1001).into()); - VersionNotifyTargets::::insert(1, v2_location, (70, Weight::zero(), 2)); - let v3_location = Parachain(1003).into_versioned(); - VersionNotifyTargets::::insert(3, v3_location, (72, Weight::zero(), 2)); + // An entry from a previous runtime with v3 XCM. + let v3_location = VersionedLocation::V3(xcm::v3::Junction::Parachain(1001).into()); + VersionNotifyTargets::::insert(3, v3_location, (70, Weight::zero(), 3)); + let v4_location = Parachain(1003).into_versioned(); + VersionNotifyTargets::::insert(4, v4_location, (72, Weight::zero(), 3)); // A runtime upgrade which alters the version does send notifications. CurrentMigration::::put(VersionMigrationStage::default()); @@ -854,11 +854,11 @@ fn subscriber_side_subscription_works() { let weight = BaseXcmWeight::get(); let message = Xcm(vec![ - // Remote supports XCM v2 + // Remote supports XCM v3 QueryResponse { query_id: 0, max_weight: Weight::zero(), - response: Response::Version(1), + response: Response::Version(3), querier: None, }, ]); @@ -872,18 +872,21 @@ fn subscriber_side_subscription_works() { ); assert_eq!(r, Outcome::Complete { used: weight }); assert_eq!(take_sent_xcm(), vec![]); - assert_eq!(XcmPallet::get_version_for(&remote), Some(1)); + assert_eq!(XcmPallet::get_version_for(&remote), Some(3)); - // This message cannot be sent to a v2 remote. - let v2_msg = xcm::v2::Xcm::<()>(vec![xcm::v2::Instruction::Trap(0)]); - assert_eq!(XcmPallet::wrap_version(&remote, v2_msg.clone()), Err(())); + // This message will be sent as v3. + let v4_msg = xcm::v4::Xcm::<()>(vec![xcm::v4::Instruction::Trap(0)]); + assert_eq!( + XcmPallet::wrap_version(&remote, v4_msg.clone()), + Ok(VersionedXcm::V3(xcm::v3::Xcm(vec![xcm::v3::Instruction::Trap(0)]))) + ); let message = Xcm(vec![ - // Remote upgraded to XCM v2 + // Remote upgraded to XCM v4 QueryResponse { query_id: 0, max_weight: Weight::zero(), - response: Response::Version(2), + response: Response::Version(4), querier: None, }, ]); @@ -897,12 +900,12 @@ fn subscriber_side_subscription_works() { ); assert_eq!(r, Outcome::Complete { used: weight }); assert_eq!(take_sent_xcm(), vec![]); - assert_eq!(XcmPallet::get_version_for(&remote), Some(2)); + assert_eq!(XcmPallet::get_version_for(&remote), Some(4)); - // This message can now be sent to remote as it's v2. + // This message is now sent as v4. assert_eq!( - XcmPallet::wrap_version(&remote, v2_msg.clone()), - Ok(VersionedXcm::from(v2_msg)) + XcmPallet::wrap_version(&remote, v4_msg.clone()), + Ok(VersionedXcm::from(v4_msg)) ); }); } @@ -911,30 +914,36 @@ fn subscriber_side_subscription_works() { #[test] fn auto_subscription_works() { new_test_ext_with_balances_and_xcm_version(vec![], None).execute_with(|| { - let remote_v2: Location = Parachain(1000).into(); + let remote_v3: Location = Parachain(1000).into(); let remote_v4: Location = Parachain(1001).into(); - assert_ok!(XcmPallet::force_default_xcm_version(RuntimeOrigin::root(), Some(2))); + assert_ok!(XcmPallet::force_default_xcm_version(RuntimeOrigin::root(), Some(3))); // Wrapping a version for a destination we don't know elicits a subscription. - let msg_v2 = xcm::v2::Xcm::<()>(vec![xcm::v2::Instruction::Trap(0)]); + let msg_v3 = xcm::v3::Xcm::<()>(vec![xcm::v3::Instruction::Trap(0)]); let msg_v4 = xcm::v4::Xcm::<()>(vec![xcm::v4::Instruction::ClearTopic]); assert_eq!( - XcmPallet::wrap_version(&remote_v2, msg_v2.clone()), - Ok(VersionedXcm::from(msg_v2.clone())), + XcmPallet::wrap_version(&remote_v3, msg_v3.clone()), + Ok(VersionedXcm::from(msg_v3.clone())), + ); + assert_eq!( + XcmPallet::wrap_version(&remote_v3, msg_v4.clone()), + Ok(VersionedXcm::V3(xcm::v3::Xcm(vec![xcm::v3::Instruction::ClearTopic]))) ); - assert_eq!(XcmPallet::wrap_version(&remote_v2, msg_v4.clone()), Err(())); - let expected = vec![(remote_v2.clone().into(), 2)]; + let expected = vec![(remote_v3.clone().into(), 2)]; assert_eq!(VersionDiscoveryQueue::::get().into_inner(), expected); assert_eq!( - XcmPallet::wrap_version(&remote_v4, msg_v2.clone()), - Ok(VersionedXcm::from(msg_v2.clone())), + XcmPallet::wrap_version(&remote_v4, msg_v3.clone()), + Ok(VersionedXcm::from(msg_v3.clone())), + ); + assert_eq!( + XcmPallet::wrap_version(&remote_v4, msg_v4.clone()), + Ok(VersionedXcm::V3(xcm::v3::Xcm(vec![xcm::v3::Instruction::ClearTopic]))) ); - assert_eq!(XcmPallet::wrap_version(&remote_v4, msg_v4.clone()), Err(())); - let expected = vec![(remote_v2.clone().into(), 2), (remote_v4.clone().into(), 2)]; + let expected = vec![(remote_v3.clone().into(), 2), (remote_v4.clone().into(), 2)]; assert_eq!(VersionDiscoveryQueue::::get().into_inner(), expected); XcmPallet::on_initialize(1); @@ -968,10 +977,10 @@ fn auto_subscription_works() { ); assert_eq!(r, Outcome::Complete { used: weight }); - // V2 messages can be sent to remote_v4 under XCM v4. + // V3 messages can be sent to remote_v4 under XCM v4. assert_eq!( - XcmPallet::wrap_version(&remote_v4, msg_v2.clone()), - Ok(VersionedXcm::from(msg_v2.clone()).into_version(4).unwrap()), + XcmPallet::wrap_version(&remote_v4, msg_v3.clone()), + Ok(VersionedXcm::from(msg_v3.clone()).into_version(4).unwrap()), ); // This message can now be sent to remote_v4 as it's v4. assert_eq!( @@ -983,26 +992,26 @@ fn auto_subscription_works() { assert_eq!( take_sent_xcm(), vec![( - remote_v2.clone(), + remote_v3.clone(), Xcm(vec![SubscribeVersion { query_id: 1, max_response_weight: Weight::zero() }]), )] ); - // Assume remote_v2 is working ok and XCM version 2. + // Assume remote_v3 is working ok and XCM version 3. let weight = BaseXcmWeight::get(); let message = Xcm(vec![ - // Remote supports XCM v2 + // Remote supports XCM v3 QueryResponse { query_id: 1, max_weight: Weight::zero(), - response: Response::Version(2), + response: Response::Version(3), querier: None, }, ]); let mut hash = fake_message_hash(&message); let r = XcmExecutor::::prepare_and_execute( - remote_v2.clone(), + remote_v3.clone(), message, &mut hash, weight, @@ -1010,12 +1019,15 @@ fn auto_subscription_works() { ); assert_eq!(r, Outcome::Complete { used: weight }); - // v4 messages cannot be sent to remote_v2... + // v4 messages cannot be sent to remote_v3... + assert_eq!( + XcmPallet::wrap_version(&remote_v3, msg_v3.clone()), + Ok(VersionedXcm::V3(msg_v3)) + ); assert_eq!( - XcmPallet::wrap_version(&remote_v2, msg_v2.clone()), - Ok(VersionedXcm::V2(msg_v2)) + XcmPallet::wrap_version(&remote_v3, msg_v4.clone()), + Ok(VersionedXcm::V3(xcm::v3::Xcm(vec![xcm::v3::Instruction::ClearTopic]))) ); - assert_eq!(XcmPallet::wrap_version(&remote_v2, msg_v4.clone()), Err(())); }) } @@ -1025,15 +1037,15 @@ fn subscription_side_upgrades_work_with_multistage_notify() { AdvertisedXcmVersion::set(1); // An entry from a previous runtime with v0 XCM. - let v2_location = VersionedLocation::V2(xcm::v2::Junction::Parachain(1001).into()); - VersionNotifyTargets::::insert(1, v2_location, (70, Weight::zero(), 1)); - let v2_location = VersionedLocation::V2(xcm::v2::Junction::Parachain(1002).into()); - VersionNotifyTargets::::insert(2, v2_location, (71, Weight::zero(), 1)); - let v3_location = Parachain(1003).into_versioned(); - VersionNotifyTargets::::insert(3, v3_location, (72, Weight::zero(), 1)); + let v3_location = VersionedLocation::V3(xcm::v3::Junction::Parachain(1001).into()); + VersionNotifyTargets::::insert(3, v3_location, (70, Weight::zero(), 3)); + let v3_location = VersionedLocation::V3(xcm::v3::Junction::Parachain(1002).into()); + VersionNotifyTargets::::insert(3, v3_location, (71, Weight::zero(), 3)); + let v4_location = Parachain(1003).into_versioned(); + VersionNotifyTargets::::insert(4, v4_location, (72, Weight::zero(), 3)); // New version. - AdvertisedXcmVersion::set(3); + AdvertisedXcmVersion::set(4); // A runtime upgrade which alters the version does send notifications. CurrentMigration::::put(VersionMigrationStage::default()); @@ -1049,19 +1061,19 @@ fn subscription_side_upgrades_work_with_multistage_notify() { let instr1 = QueryResponse { query_id: 70, max_weight: Weight::zero(), - response: Response::Version(3), + response: Response::Version(4), querier: None, }; let instr2 = QueryResponse { query_id: 71, max_weight: Weight::zero(), - response: Response::Version(3), + response: Response::Version(4), querier: None, }; let instr3 = QueryResponse { query_id: 72, max_weight: Weight::zero(), - response: Response::Version(3), + response: Response::Version(4), querier: None, }; let mut sent = take_sent_xcm(); @@ -1083,9 +1095,9 @@ fn subscription_side_upgrades_work_with_multistage_notify() { assert_eq!( contents, vec![ - (XCM_VERSION, Parachain(1001).into_versioned(), (70, Weight::zero(), 3)), - (XCM_VERSION, Parachain(1002).into_versioned(), (71, Weight::zero(), 3)), - (XCM_VERSION, Parachain(1003).into_versioned(), (72, Weight::zero(), 3)), + (XCM_VERSION, Parachain(1001).into_versioned(), (70, Weight::zero(), 4)), + (XCM_VERSION, Parachain(1002).into_versioned(), (71, Weight::zero(), 4)), + (XCM_VERSION, Parachain(1003).into_versioned(), (72, Weight::zero(), 4)), ] ); }); diff --git a/polkadot/xcm/procedural/tests/conversion_functions.rs b/polkadot/xcm/procedural/tests/conversion_functions.rs index 5b6965167fcd..7d2698d2cd77 100644 --- a/polkadot/xcm/procedural/tests/conversion_functions.rs +++ b/polkadot/xcm/procedural/tests/conversion_functions.rs @@ -14,10 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -use xcm::v2::prelude::*; +use xcm::v3::prelude::*; #[test] -fn slice_syntax_in_v2_works() { +fn slice_syntax_in_v3_works() { let old_junctions = Junctions::X2(Parachain(1), PalletInstance(1)); let new_junctions = Junctions::from([Parachain(1), PalletInstance(1)]); assert_eq!(old_junctions, new_junctions); diff --git a/polkadot/xcm/src/lib.rs b/polkadot/xcm/src/lib.rs index 513dfe5501ba..8b0030e59b5f 100644 --- a/polkadot/xcm/src/lib.rs +++ b/polkadot/xcm/src/lib.rs @@ -21,6 +21,8 @@ // // Hence, `no_std` rather than sp-runtime. #![cfg_attr(not(feature = "std"), no_std)] +// Because of XCMv2. +#![allow(deprecated)] extern crate alloc; @@ -28,6 +30,9 @@ use derivative::Derivative; use parity_scale_codec::{Decode, DecodeLimit, Encode, Error as CodecError, Input, MaxEncodedLen}; use scale_info::TypeInfo; +#[deprecated( + note = "XCMv2 will be removed once XCMv5 is released. Please use XCMv3 or XCMv4 instead." +)] pub mod v2; pub mod v3; pub mod v4; @@ -425,6 +430,7 @@ pub type VersionedMultiAssets = VersionedAssets; #[scale_info(replace_segment("staging_xcm", "xcm"))] pub enum VersionedXcm { #[codec(index = 2)] + #[deprecated] V2(v2::Xcm), #[codec(index = 3)] V3(v3::Xcm), diff --git a/polkadot/xcm/src/tests.rs b/polkadot/xcm/src/tests.rs index 1aabbcef281d..4c666063f3f4 100644 --- a/polkadot/xcm/src/tests.rs +++ b/polkadot/xcm/src/tests.rs @@ -158,18 +158,6 @@ fn encode_decode_versioned_multi_assets_v3() { assert_eq!(assets, decoded); } -#[test] -fn encode_decode_versioned_xcm_v2() { - let xcm = VersionedXcm::V2(v2::Xcm::<()>::new()); - let encoded = xcm.encode(); - - assert_eq!(encoded, hex_literal::hex!("0200"), "encode format changed"); - assert_eq!(encoded[0], 2, "bad version number"); - - let decoded = VersionedXcm::decode(&mut &encoded[..]).unwrap(); - assert_eq!(xcm, decoded); -} - #[test] fn encode_decode_versioned_xcm_v3() { let xcm = VersionedXcm::V3(v3::Xcm::<()>::new()); diff --git a/polkadot/xcm/src/v2/mod.rs b/polkadot/xcm/src/v2/mod.rs index 347f3f2c2920..7b6858e6a5c2 100644 --- a/polkadot/xcm/src/v2/mod.rs +++ b/polkadot/xcm/src/v2/mod.rs @@ -15,6 +15,9 @@ // along with Cumulus. If not, see . //! # XCM Version 2 +//! +//! WARNING: DEPRECATED, please use version 3 or 4. +//! //! Version 2 of the Cross-Consensus Message format data structures. The comprehensive list of //! changes can be found in //! [this PR description](https://github.com/paritytech/polkadot/pull/3629#issue-968428279). @@ -52,8 +55,8 @@ use super::{ v3::{ BodyId as NewBodyId, BodyPart as NewBodyPart, Instruction as NewInstruction, - NetworkId as NewNetworkId, Response as NewResponse, WeightLimit as NewWeightLimit, - Xcm as NewXcm, + NetworkId as NewNetworkId, OriginKind as NewOriginKind, Response as NewResponse, + WeightLimit as NewWeightLimit, Xcm as NewXcm, }, DoubleEncoded, }; @@ -104,6 +107,18 @@ pub enum OriginKind { Xcm, } +impl From for OriginKind { + fn from(new: NewOriginKind) -> Self { + use NewOriginKind::*; + match new { + Native => Self::Native, + SovereignAccount => Self::SovereignAccount, + Superuser => Self::Superuser, + Xcm => Self::Xcm, + } + } +} + /// A global identifier of an account-bearing consensus system. #[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)] #[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] @@ -262,6 +277,7 @@ pub const VERSION: super::Version = 2; /// An identifier for a query. pub type QueryId = u64; +/// DEPRECATED. Please use XCMv3 or XCMv4 instead. #[derive(Derivative, Default, Encode, Decode, TypeInfo)] #[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))] #[codec(encode_bound())] @@ -1065,7 +1081,7 @@ impl TryFrom> for Instruction Self::HrmpChannelClosing { initiator, sender, recipient }, Transact { origin_kind, require_weight_at_most, call } => Self::Transact { - origin_type: origin_kind, + origin_type: origin_kind.into(), require_weight_at_most: require_weight_at_most.ref_time(), call: call.into(), }, diff --git a/polkadot/xcm/src/v3/mod.rs b/polkadot/xcm/src/v3/mod.rs index e7c57f414eb7..8ff661a9bbac 100644 --- a/polkadot/xcm/src/v3/mod.rs +++ b/polkadot/xcm/src/v3/mod.rs @@ -16,15 +16,14 @@ //! Version 3 of the Cross-Consensus Message format data structures. -use super::{ - v2::{ - Instruction as OldInstruction, Response as OldResponse, WeightLimit as OldWeightLimit, - Xcm as OldXcm, - }, - v4::{ - Instruction as NewInstruction, PalletInfo as NewPalletInfo, - QueryResponseInfo as NewQueryResponseInfo, Response as NewResponse, Xcm as NewXcm, - }, +#[allow(deprecated)] +use super::v2::{ + Instruction as OldInstruction, OriginKind as OldOriginKind, Response as OldResponse, + WeightLimit as OldWeightLimit, Xcm as OldXcm, +}; +use super::v4::{ + Instruction as NewInstruction, PalletInfo as NewPalletInfo, + QueryResponseInfo as NewQueryResponseInfo, Response as NewResponse, Xcm as NewXcm, }; use crate::DoubleEncoded; use alloc::{vec, vec::Vec}; @@ -53,11 +52,46 @@ pub use multilocation::{ Ancestor, AncestorThen, InteriorMultiLocation, Location, MultiLocation, Parent, ParentThen, }; pub use traits::{ - send_xcm, validate_send, Error, ExecuteXcm, Outcome, PreparedMessage, Result, SendError, - SendResult, SendXcm, Weight, XcmHash, + send_xcm, validate_send, Error, ExecuteXcm, GetWeight, Outcome, PreparedMessage, Result, + SendError, SendResult, SendXcm, Weight, XcmHash, }; -// These parts of XCM v2 are unchanged in XCM v3, and are re-imported here. -pub use super::v2::{GetWeight, OriginKind}; + +/// Basically just the XCM (more general) version of `ParachainDispatchOrigin`. +#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo)] +#[scale_info(replace_segment("staging_xcm", "xcm"))] +#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))] +pub enum OriginKind { + /// Origin should just be the native dispatch origin representation for the sender in the + /// local runtime framework. For Cumulus/Frame chains this is the `Parachain` or `Relay` origin + /// if coming from a chain, though there may be others if the `MultiLocation` XCM origin has a + /// primary/native dispatch origin form. + Native, + + /// Origin should just be the standard account-based origin with the sovereign account of + /// the sender. For Cumulus/Frame chains, this is the `Signed` origin. + SovereignAccount, + + /// Origin should be the super-user. For Cumulus/Frame chains, this is the `Root` origin. + /// This will not usually be an available option. + Superuser, + + /// Origin should be interpreted as an XCM native origin and the `MultiLocation` should be + /// encoded directly in the dispatch origin unchanged. For Cumulus/Frame chains, this will be + /// the `pallet_xcm::Origin::Xcm` type. + Xcm, +} + +impl From for OriginKind { + fn from(old: OldOriginKind) -> Self { + use OldOriginKind::*; + match old { + Native => Self::Native, + SovereignAccount => Self::SovereignAccount, + Superuser => Self::Superuser, + Xcm => Self::Xcm, + } + } +} /// This module's XCM version. pub const VERSION: super::Version = 3; @@ -1310,6 +1344,7 @@ impl TryFrom for Response { } // Convert from a v2 XCM to a v3 XCM. +#[allow(deprecated)] impl TryFrom> for Xcm { type Error = (); fn try_from(old_xcm: OldXcm) -> result::Result { @@ -1500,7 +1535,7 @@ impl TryFrom> for Instruction { HrmpChannelClosing { initiator, sender, recipient } => Self::HrmpChannelClosing { initiator, sender, recipient }, Transact { origin_type, require_weight_at_most, call } => Self::Transact { - origin_kind: origin_type, + origin_kind: origin_type.into(), require_weight_at_most: Weight::from_parts( require_weight_at_most, DEFAULT_PROOF_SIZE, @@ -1572,118 +1607,6 @@ impl TryFrom> for Instruction { #[cfg(test)] mod tests { use super::{prelude::*, *}; - use crate::v2::{ - Junctions::Here as OldHere, MultiAssetFilter as OldMultiAssetFilter, - WildMultiAsset as OldWildMultiAsset, - }; - - #[test] - fn basic_roundtrip_works() { - let xcm = Xcm::<()>(vec![TransferAsset { - assets: (Here, 1u128).into(), - beneficiary: Here.into(), - }]); - let old_xcm = OldXcm::<()>(vec![OldInstruction::TransferAsset { - assets: (OldHere, 1).into(), - beneficiary: OldHere.into(), - }]); - assert_eq!(old_xcm, OldXcm::<()>::try_from(xcm.clone()).unwrap()); - let new_xcm: Xcm<()> = old_xcm.try_into().unwrap(); - assert_eq!(new_xcm, xcm); - } - - #[test] - fn teleport_roundtrip_works() { - let xcm = Xcm::<()>(vec![ - ReceiveTeleportedAsset((Here, 1u128).into()), - ClearOrigin, - DepositAsset { assets: Wild(AllCounted(1)), beneficiary: Here.into() }, - ]); - let old_xcm: OldXcm<()> = OldXcm::<()>(vec![ - OldInstruction::ReceiveTeleportedAsset((OldHere, 1).into()), - OldInstruction::ClearOrigin, - OldInstruction::DepositAsset { - assets: crate::v2::MultiAssetFilter::Wild(crate::v2::WildMultiAsset::All), - max_assets: 1, - beneficiary: OldHere.into(), - }, - ]); - assert_eq!(old_xcm, OldXcm::<()>::try_from(xcm.clone()).unwrap()); - let new_xcm: Xcm<()> = old_xcm.try_into().unwrap(); - assert_eq!(new_xcm, xcm); - } - - #[test] - fn reserve_deposit_roundtrip_works() { - let xcm = Xcm::<()>(vec![ - ReserveAssetDeposited((Here, 1u128).into()), - ClearOrigin, - BuyExecution { - fees: (Here, 1u128).into(), - weight_limit: Some(Weight::from_parts(1, DEFAULT_PROOF_SIZE)).into(), - }, - DepositAsset { assets: Wild(AllCounted(1)), beneficiary: Here.into() }, - ]); - let old_xcm = OldXcm::<()>(vec![ - OldInstruction::ReserveAssetDeposited((OldHere, 1).into()), - OldInstruction::ClearOrigin, - OldInstruction::BuyExecution { - fees: (OldHere, 1).into(), - weight_limit: Some(1).into(), - }, - OldInstruction::DepositAsset { - assets: crate::v2::MultiAssetFilter::Wild(crate::v2::WildMultiAsset::All), - max_assets: 1, - beneficiary: OldHere.into(), - }, - ]); - assert_eq!(old_xcm, OldXcm::<()>::try_from(xcm.clone()).unwrap()); - let new_xcm: Xcm<()> = old_xcm.try_into().unwrap(); - assert_eq!(new_xcm, xcm); - } - - #[test] - fn deposit_asset_roundtrip_works() { - let xcm = Xcm::<()>(vec![ - WithdrawAsset((Here, 1u128).into()), - DepositAsset { assets: Wild(AllCounted(1)), beneficiary: Here.into() }, - ]); - let old_xcm = OldXcm::<()>(vec![ - OldInstruction::WithdrawAsset((OldHere, 1).into()), - OldInstruction::DepositAsset { - assets: OldMultiAssetFilter::Wild(OldWildMultiAsset::All), - max_assets: 1, - beneficiary: OldHere.into(), - }, - ]); - assert_eq!(old_xcm, OldXcm::<()>::try_from(xcm.clone()).unwrap()); - let new_xcm: Xcm<()> = old_xcm.try_into().unwrap(); - assert_eq!(new_xcm, xcm); - } - - #[test] - fn deposit_reserve_asset_roundtrip_works() { - let xcm = Xcm::<()>(vec![ - WithdrawAsset((Here, 1u128).into()), - DepositReserveAsset { - assets: Wild(AllCounted(1)), - dest: Here.into(), - xcm: Xcm::<()>(vec![]), - }, - ]); - let old_xcm = OldXcm::<()>(vec![ - OldInstruction::WithdrawAsset((OldHere, 1).into()), - OldInstruction::DepositReserveAsset { - assets: OldMultiAssetFilter::Wild(OldWildMultiAsset::All), - max_assets: 1, - dest: OldHere.into(), - xcm: OldXcm::<()>(vec![]), - }, - ]); - assert_eq!(old_xcm, OldXcm::<()>::try_from(xcm.clone()).unwrap()); - let new_xcm: Xcm<()> = old_xcm.try_into().unwrap(); - assert_eq!(new_xcm, xcm); - } #[test] fn decoding_respects_limit() { diff --git a/polkadot/xcm/src/v3/traits.rs b/polkadot/xcm/src/v3/traits.rs index cfe387df1a86..680e0bacd0c9 100644 --- a/polkadot/xcm/src/v3/traits.rs +++ b/polkadot/xcm/src/v3/traits.rs @@ -25,6 +25,11 @@ pub use sp_weights::Weight; use super::*; +// A simple trait to get the weight of some object. +pub trait GetWeight { + fn weight(&self) -> sp_weights::Weight; +} + /// Error codes used in XCM. The first errors codes have explicit indices and are part of the XCM /// format. Those trailing are merely part of the XCM implementation; there is no expectation that /// they will retain the same index over time. diff --git a/polkadot/xcm/src/v4/mod.rs b/polkadot/xcm/src/v4/mod.rs index 77b6d915fcb5..e1ca60087b19 100644 --- a/polkadot/xcm/src/v4/mod.rs +++ b/polkadot/xcm/src/v4/mod.rs @@ -16,7 +16,7 @@ //! Version 4 of the Cross-Consensus Message format data structures. -pub use super::v2::GetWeight; +pub use super::v3::GetWeight; use super::v3::{ Instruction as OldInstruction, PalletInfo as OldPalletInfo, QueryResponseInfo as OldQueryResponseInfo, Response as OldResponse, Xcm as OldXcm, diff --git a/polkadot/xcm/xcm-builder/src/process_xcm_message.rs b/polkadot/xcm/xcm-builder/src/process_xcm_message.rs index 7760274f6e24..449cda3d2323 100644 --- a/polkadot/xcm/xcm-builder/src/process_xcm_message.rs +++ b/polkadot/xcm/xcm-builder/src/process_xcm_message.rs @@ -124,7 +124,7 @@ mod tests { }; use parity_scale_codec::Encode; use polkadot_test_runtime::*; - use xcm::{v2, v3, VersionedXcm}; + use xcm::{v3, v4, VersionedXcm}; const ORIGIN: Junction = Junction::OnlyChild; /// The processor to use for tests. @@ -134,8 +134,8 @@ mod tests { #[test] fn process_message_trivial_works() { // ClearOrigin works. - assert!(process(v2_xcm(true)).unwrap()); assert!(process(v3_xcm(true)).unwrap()); + assert!(process(v4_xcm(true)).unwrap()); } #[test] @@ -194,7 +194,7 @@ mod tests { #[test] fn process_message_overweight_fails() { - for msg in [v3_xcm(true), v3_xcm(false), v3_xcm(false), v2_xcm(false)] { + for msg in [v4_xcm(true), v4_xcm(false), v4_xcm(false), v3_xcm(false)] { let msg = &msg.encode()[..]; // Errors if we stay below a weight limit of 1000. @@ -216,7 +216,7 @@ mod tests { } } - fn v2_xcm(success: bool) -> VersionedXcm { + fn v3_xcm(success: bool) -> VersionedXcm { let instr = if success { v3::Instruction::::ClearOrigin } else { @@ -225,13 +225,13 @@ mod tests { VersionedXcm::V3(v3::Xcm::(vec![instr])) } - fn v3_xcm(success: bool) -> VersionedXcm { + fn v4_xcm(success: bool) -> VersionedXcm { let instr = if success { - v2::Instruction::::ClearOrigin + v4::Instruction::::ClearOrigin } else { - v2::Instruction::::Trap(1) + v4::Instruction::::Trap(1) }; - VersionedXcm::V2(v2::Xcm::(vec![instr])) + VersionedXcm::V4(v4::Xcm::(vec![instr])) } fn process(msg: VersionedXcm) -> Result { diff --git a/prdoc/pr_4131.prdoc b/prdoc/pr_4131.prdoc new file mode 100644 index 000000000000..b0619eabe13b --- /dev/null +++ b/prdoc/pr_4131.prdoc @@ -0,0 +1,26 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Deprecate XCMv2 + +doc: + - audience: Runtime Dev + description: | + XCMv2 has been deprecated. It will be removed when XCMv5 is released. + Use version 3 or 4 instead. + - audience: Runtime User + description: | + XCMv2 has been deprecated. It will be removed when XCMv5 is released. + Use version 3 or 4 instead. + +crates: +- name: staging-xcm + bump: minor +- name: xcm-procedural + bump: minor +- name: staging-xcm-builder + bump: minor +- name: pallet-xcm + bump: minor +- name: cumulus-pallet-xcmp-queue + bump: minor diff --git a/prdoc/schema_user.json b/prdoc/schema_user.json index 294005f209d5..e6c0468aaf85 100644 --- a/prdoc/schema_user.json +++ b/prdoc/schema_user.json @@ -218,7 +218,7 @@ }, "doc": { "type": "object", - "description": "You have the the option to provide different description of your PR for different audiences.", + "description": "You have the option to provide different description of your PR for different audiences.", "additionalProperties": false, "properties": { "audience": { diff --git a/substrate/bin/utils/chain-spec-builder/src/lib.rs b/substrate/bin/utils/chain-spec-builder/src/lib.rs index 7982da76227a..167704d3633d 100644 --- a/substrate/bin/utils/chain-spec-builder/src/lib.rs +++ b/substrate/bin/utils/chain-spec-builder/src/lib.rs @@ -206,9 +206,14 @@ struct NamedPresetCmd { /// /// The code field of the chain spec will be updated with the runtime provided in the /// command line. This operation supports both plain and raw formats. +/// +/// This command does not update chain-spec file in-place. The result of this command will be stored +/// in a file given as `-c/--chain-spec-path` command line argument. #[derive(Parser, Debug, Clone)] pub struct UpdateCodeCmd { /// Chain spec to be updated. + /// + /// Please note that the file will not be updated in-place. pub input_chain_spec: PathBuf, /// The path to new runtime wasm blob to be stored into chain-spec. pub runtime_wasm_path: PathBuf, diff --git a/substrate/bin/utils/subkey/README.md b/substrate/bin/utils/subkey/README.md index fc1053e232d7..5c6dda37edf6 100644 --- a/substrate/bin/utils/subkey/README.md +++ b/substrate/bin/utils/subkey/README.md @@ -74,7 +74,7 @@ The output above shows a **secret phrase** (also called **mnemonic phrase**) and **Private Key**). Those 2 secrets are the pieces of information you MUST keep safe and secret. All the other information below can be derived from those secrets. -The output above also show the **public key** and the **Account ID**. Those are the independent from the network where +The output above also shows the **public key** and the **Account ID**. Those are the independent from the network where you will use the key. The **SS58 address** (or **Public Address**) of a new account is a representation of the public keys of an account for @@ -152,7 +152,7 @@ subkey inspect "soup lyrics media market way crouch elevator put moon useful que which recovers the account `5Fe4sqj2K4fRuzEGvToi4KATqZfiDU7TqynjXG6PZE2dxwyh` and not `5He5pZpc7AJ8evPuab37vJF6KkFDqq9uDq2WXh877Qw6iaVC` as we expected. The additional user-defined **password** -(`extra_secret` in our example) is now required to fully recover the account. Let's inspect the the previous mnemonic, +(`extra_secret` in our example) is now required to fully recover the account. Let's inspect the previous mnemonic, this time passing also the required `password` as shown below: ```bash diff --git a/substrate/client/network/Cargo.toml b/substrate/client/network/Cargo.toml index b06d9c73540c..29b14a4511ca 100644 --- a/substrate/client/network/Cargo.toml +++ b/substrate/client/network/Cargo.toml @@ -59,7 +59,7 @@ sp-blockchain = { path = "../../primitives/blockchain" } sp-core = { path = "../../primitives/core" } sp-runtime = { path = "../../primitives/runtime" } wasm-timer = "0.2" -litep2p = "0.4.0" +litep2p = "0.5.0" once_cell = "1.18.0" void = "1.0.2" schnellru = "0.2.1" diff --git a/substrate/client/network/src/litep2p/discovery.rs b/substrate/client/network/src/litep2p/discovery.rs index 351380755dbd..ff5f492df246 100644 --- a/substrate/client/network/src/litep2p/discovery.rs +++ b/substrate/client/network/src/litep2p/discovery.rs @@ -34,7 +34,7 @@ use litep2p::{ identify::{Config as IdentifyConfig, IdentifyEvent}, kademlia::{ Config as KademliaConfig, ConfigBuilder as KademliaConfigBuilder, KademliaEvent, - KademliaHandle, QueryId, Quorum, Record, RecordKey, + KademliaHandle, QueryId, Quorum, Record, RecordKey, RecordsType, }, ping::{Config as PingConfig, PingEvent}, }, @@ -123,8 +123,8 @@ pub enum DiscoveryEvent { /// Query ID. query_id: QueryId, - /// Record. - record: Record, + /// Records. + records: RecordsType, }, /// Record was successfully stored on the DHT. @@ -460,16 +460,13 @@ impl Stream for Discovery { peers: peers.into_iter().collect(), })) }, - Poll::Ready(Some(KademliaEvent::GetRecordSuccess { query_id, record })) => { + Poll::Ready(Some(KademliaEvent::GetRecordSuccess { query_id, records })) => { log::trace!( target: LOG_TARGET, - "`GET_RECORD` succeeded for {query_id:?}: {record:?}", + "`GET_RECORD` succeeded for {query_id:?}: {records:?}", ); - return Poll::Ready(Some(DiscoveryEvent::GetRecordSuccess { - query_id, - record: record.record, - })); + return Poll::Ready(Some(DiscoveryEvent::GetRecordSuccess { query_id, records })); }, Poll::Ready(Some(KademliaEvent::PutRecordSucess { query_id, key: _ })) => return Poll::Ready(Some(DiscoveryEvent::PutRecordSuccess { query_id })), diff --git a/substrate/client/network/src/litep2p/mod.rs b/substrate/client/network/src/litep2p/mod.rs index 67085a81a5c8..ae287052b2d4 100644 --- a/substrate/client/network/src/litep2p/mod.rs +++ b/substrate/client/network/src/litep2p/mod.rs @@ -56,7 +56,10 @@ use litep2p::{ crypto::ed25519::Keypair, executor::Executor, protocol::{ - libp2p::{bitswap::Config as BitswapConfig, kademlia::QueryId}, + libp2p::{ + bitswap::Config as BitswapConfig, + kademlia::{QueryId, RecordsType}, + }, request_response::ConfigBuilder as RequestResponseConfigBuilder, }, transport::{ @@ -796,23 +799,30 @@ impl NetworkBackend for Litep2pNetworkBac self.peerstore_handle.add_known_peer(peer.into()); } } - Some(DiscoveryEvent::GetRecordSuccess { query_id, record }) => { + Some(DiscoveryEvent::GetRecordSuccess { query_id, records }) => { match self.pending_get_values.remove(&query_id) { None => log::warn!( target: LOG_TARGET, "`GET_VALUE` succeeded for a non-existent query", ), - Some((_key, started)) => { + Some((key, started)) => { log::trace!( target: LOG_TARGET, "`GET_VALUE` for {:?} ({query_id:?}) succeeded", - record.key, + key, ); - self.event_streams.send(Event::Dht( - DhtEvent::ValueFound(vec![ + let value_found = match records { + RecordsType::LocalStore(record) => vec![ (libp2p::kad::RecordKey::new(&record.key), record.value) - ]) + ], + RecordsType::Network(records) => records.into_iter().map(|peer_record| { + (libp2p::kad::RecordKey::new(&peer_record.record.key), peer_record.record.value) + }).collect(), + }; + + self.event_streams.send(Event::Dht( + DhtEvent::ValueFound(value_found) )); if let Some(ref metrics) = self.metrics { diff --git a/substrate/client/network/types/Cargo.toml b/substrate/client/network/types/Cargo.toml index ed89eca2dd1f..a9334aaa1705 100644 --- a/substrate/client/network/types/Cargo.toml +++ b/substrate/client/network/types/Cargo.toml @@ -13,7 +13,7 @@ documentation = "https://docs.rs/sc-network-types" bs58 = "0.5.0" ed25519-dalek = "2.1" libp2p-identity = { version = "0.1.3", features = ["ed25519", "peerid"] } -litep2p = "0.4.0" +litep2p = "0.5.0" multiaddr = "0.17.0" multihash = { version = "0.17.0", default-features = false, features = ["identity", "multihash-impl", "sha2", "std"] } rand = "0.8.5" diff --git a/substrate/client/transaction-pool/README.md b/substrate/client/transaction-pool/README.md index 7a53727d5761..30a3a8118b52 100644 --- a/substrate/client/transaction-pool/README.md +++ b/substrate/client/transaction-pool/README.md @@ -49,7 +49,7 @@ pool, it's broadcasting status, block inclusion, finality, etc. ## Transaction Validity details -Information retrieved from the the runtime are encapsulated in the `TransactionValidity` +Information retrieved from the runtime are encapsulated in the `TransactionValidity` type. ```rust diff --git a/substrate/frame/contracts/README.md b/substrate/frame/contracts/README.md index 2e70b5c5008b..6440f14b9ece 100644 --- a/substrate/frame/contracts/README.md +++ b/substrate/frame/contracts/README.md @@ -112,7 +112,7 @@ Contracts can emit messages to the client when called as RPC through the API. This is exposed in [ink!](https://use.ink) via [`ink_env::debug_message()`](https://paritytech.github.io/ink/ink_env/fn.debug_message.html). -Those messages are gathered into an internal buffer and sent to the RPC client. It is up the the individual client if +Those messages are gathered into an internal buffer and sent to the RPC client. It is up to the individual client if and how those messages are presented to the user. This buffer is also printed as a debug message. In order to see these messages on the node console the log level for the diff --git a/substrate/utils/frame/benchmarking-cli/src/overhead/README.md b/substrate/utils/frame/benchmarking-cli/src/overhead/README.md index 648908010ba0..cee095fb8cad 100644 --- a/substrate/utils/frame/benchmarking-cli/src/overhead/README.md +++ b/substrate/utils/frame/benchmarking-cli/src/overhead/README.md @@ -108,7 +108,7 @@ The complete command for Polkadot looks like this: cargo run --profile=production -- benchmark overhead --chain=polkadot-dev --wasm-execution=compiled --weight-path=runtime/polkadot/constants/src/weights/ ``` -This will overwrite the the +This will overwrite the [block_weights.rs](https://github.com/paritytech/polkadot/blob/c254e5975711a6497af256f6831e9a6c752d28f5/runtime/polkadot/constants/src/weights/block_weights.rs) and [extrinsic_weights.rs](https://github.com/paritytech/polkadot/blob/c254e5975711a6497af256f6831e9a6c752d28f5/runtime/polkadot/constants/src/weights/extrinsic_weights.rs)