diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d158953088c5..cf75b74f11a9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -298,22 +298,6 @@ build-malus: #### stage: build -check-transaction-versions: - image: node:15 - stage: build - <<: *rules-test - <<: *docker-env - <<: *vault-secrets - needs: - - job: test-build-linux-stable - artifacts: true - before_script: - - apt-get -y update; apt-get -y install jq lsof - - npm install --ignore-scripts -g @polkadot/metadata-cmp - - git fetch origin release - script: - - scripts/gitlab/check_extrinsics_ordering.sh - generate-impl-guide: stage: build <<: *rules-test diff --git a/Cargo.lock b/Cargo.lock index a77bbc01c18b..35cf3233a006 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -723,6 +723,7 @@ dependencies = [ "finality-grandpa", "frame-support", "parity-scale-codec", + "scale-info", "serde", "sp-core", "sp-finality-grandpa", @@ -737,6 +738,7 @@ dependencies = [ "bp-runtime", "frame-support", "parity-scale-codec", + "scale-info", "sp-std", ] @@ -750,6 +752,7 @@ dependencies = [ "frame-system", "impl-trait-for-tuples", "parity-scale-codec", + "scale-info", "serde", "sp-std", ] @@ -764,6 +767,7 @@ dependencies = [ "frame-system", "hex", "parity-scale-codec", + "scale-info", "sp-api", "sp-core", "sp-runtime", @@ -809,6 +813,7 @@ dependencies = [ "hash-db", "num-traits", "parity-scale-codec", + "scale-info", "sp-core", "sp-io", "sp-runtime", @@ -860,6 +865,7 @@ dependencies = [ "pallet-bridge-messages", "pallet-transaction-payment", "parity-scale-codec", + "scale-info", "sp-core", "sp-runtime", "sp-state-machine", @@ -1867,9 +1873,9 @@ dependencies = [ [[package]] name = "finality-grandpa" -version = "0.14.1" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74a1bfdcc776e63e49f741c7ce6116fa1b887e8ac2e3ccb14dd4aa113e54feb9" +checksum = "e8ac3ff5224ef91f3c97e03eb1de2db82743427e91aaa5ac635f454f0b164f5a" dependencies = [ "either", "futures 0.3.17", @@ -1878,6 +1884,7 @@ dependencies = [ "num-traits", "parity-scale-codec", "parking_lot 0.11.1", + "scale-info", ] [[package]] @@ -3181,6 +3188,7 @@ dependencies = [ "polkadot-runtime-common", "polkadot-runtime-parachains", "rustc-hex", + "scale-info", "separator", "serde", "serde_derive", @@ -4652,6 +4660,7 @@ dependencies = [ "frame-system", "log", "parity-scale-codec", + "scale-info", "serde", "sp-core", "sp-io", @@ -4673,6 +4682,7 @@ dependencies = [ "log", "num-traits", "parity-scale-codec", + "scale-info", "serde", "sp-finality-grandpa", "sp-io", @@ -4699,6 +4709,7 @@ dependencies = [ "num-traits", "pallet-balances", "parity-scale-codec", + "scale-info", "serde", "sp-core", "sp-io", @@ -5275,6 +5286,7 @@ dependencies = [ "parity-scale-codec", "polkadot-parachain", "polkadot-runtime-parachains", + "scale-info", "serde", "sp-core", "sp-io", @@ -5845,6 +5857,7 @@ version = "0.9.9" dependencies = [ "parity-scale-codec", "parity-util-mem", + "scale-info", "sp-core", "sp-runtime", "sp-std", @@ -6456,6 +6469,7 @@ dependencies = [ "parity-scale-codec", "parity-util-mem", "polkadot-core-primitives", + "scale-info", "serde", "sp-core", "sp-runtime", @@ -6473,6 +6487,7 @@ dependencies = [ "parity-util-mem", "polkadot-core-primitives", "polkadot-parachain", + "scale-info", "serde", "sp-api", "sp-application-crypto", @@ -6572,6 +6587,7 @@ dependencies = [ "polkadot-primitives", "polkadot-runtime-common", "rustc-hex", + "scale-info", "separator", "serde", "serde_derive", @@ -6604,6 +6620,7 @@ dependencies = [ name = "polkadot-runtime-common" version = "0.9.9" dependencies = [ + "beefy-primitives", "bitvec 0.20.1", "frame-benchmarking", "frame-election-provider-support", @@ -6629,6 +6646,7 @@ dependencies = [ "polkadot-primitives", "polkadot-runtime-parachains", "rustc-hex", + "scale-info", "serde", "serde_derive", "serde_json", @@ -6674,6 +6692,7 @@ dependencies = [ "rand_chacha 0.3.1", "rustc-hex", "sc-keystore", + "scale-info", "serde", "sp-api", "sp-core", @@ -6924,9 +6943,11 @@ dependencies = [ "polkadot-node-core-pvf", "polkadot-node-primitives", "polkadot-node-subsystem", + "polkadot-node-subsystem-test-helpers", "polkadot-node-subsystem-types", "polkadot-node-subsystem-util", "polkadot-primitives", + "sp-core", "sp-keystore", "structopt", "tracing", @@ -6969,6 +6990,7 @@ dependencies = [ "polkadot-runtime-common", "polkadot-runtime-parachains", "rustc-hex", + "scale-info", "serde", "serde_derive", "serde_json", @@ -7728,6 +7750,7 @@ dependencies = [ "polkadot-primitives", "polkadot-runtime-common", "polkadot-runtime-parachains", + "scale-info", "serde", "serde_derive", "smallvec", @@ -11393,6 +11416,7 @@ dependencies = [ "polkadot-runtime-common", "polkadot-runtime-parachains", "rustc-hex", + "scale-info", "serde", "serde_derive", "serde_json", @@ -11524,6 +11548,7 @@ dependencies = [ "impl-trait-for-tuples", "log", "parity-scale-codec", + "scale-info", "xcm-procedural", ] @@ -11540,6 +11565,7 @@ dependencies = [ "parity-scale-codec", "polkadot-parachain", "polkadot-runtime-parachains", + "scale-info", "sp-arithmetic", "sp-core", "sp-io", @@ -11622,6 +11648,7 @@ dependencies = [ "polkadot-core-primitives", "polkadot-parachain", "polkadot-runtime-parachains", + "scale-info", "sp-core", "sp-io", "sp-runtime", diff --git a/README.md b/README.md index d5251eb319d1..034a23a59e62 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,22 @@ cargo build --release Note that compilation is a memory intensive process. We recommend having 4 GiB of physical RAM or swap available (keep in mind that if a build hits swap it tends to be very slow). +#### Build from Source with Docker + +You can also build from source using +[Parity CI docker image](https://github.com/paritytech/scripts/tree/master/dockerfiles/ci-linux): + +```bash +git checkout +docker run --rm -it -w /shellhere/polkadot \ + -v $(pwd):/shellhere/polkadot \ + paritytech/ci-linux:production cargo build --release +sudo chown -R $(id -u):$(id -g) target/ +``` + +If you want to reproduce other steps of CI process you can use the following +[guide](https://github.com/paritytech/scripts#gitlab-ci-for-building-docker-images). + ## Networks This repo supports runtimes for Polkadot, Kusama, and Westend. diff --git a/bridges/bin/millau/runtime/src/lib.rs b/bridges/bin/millau/runtime/src/lib.rs index 2e14a551db8b..6e561e8719e4 100644 --- a/bridges/bin/millau/runtime/src/lib.rs +++ b/bridges/bin/millau/runtime/src/lib.rs @@ -465,7 +465,7 @@ impl_runtime_apis! { impl sp_api::Metadata for Runtime { fn metadata() -> OpaqueMetadata { - Runtime::metadata().into() + OpaqueMetadata::new(Runtime::metadata().into()) } } diff --git a/bridges/bin/rialto/runtime/src/lib.rs b/bridges/bin/rialto/runtime/src/lib.rs index 62e3fb07b517..bc7a4d8f7073 100644 --- a/bridges/bin/rialto/runtime/src/lib.rs +++ b/bridges/bin/rialto/runtime/src/lib.rs @@ -590,7 +590,7 @@ impl_runtime_apis! { impl sp_api::Metadata for Runtime { fn metadata() -> OpaqueMetadata { - Runtime::metadata().into() + OpaqueMetadata::new(Runtime::metadata().into()) } } diff --git a/bridges/bin/runtime-common/Cargo.toml b/bridges/bin/runtime-common/Cargo.toml index 07fe8910c21f..928523af0256 100644 --- a/bridges/bin/runtime-common/Cargo.toml +++ b/bridges/bin/runtime-common/Cargo.toml @@ -11,6 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } ed25519-dalek = { version = "1.0", default-features = false, optional = true } hash-db = { version = "0.15.2", default-features = false } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } # Bridge dependencies @@ -40,10 +41,12 @@ std = [ "codec/std", "frame-support/std", "hash-db/std", + "scale-info/std", "pallet-bridge-dispatch/std", "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", "pallet-transaction-payment/std", + "scale-info/std", "sp-core/std", "sp-runtime/std", "sp-state-machine/std", diff --git a/bridges/bin/runtime-common/src/messages.rs b/bridges/bin/runtime-common/src/messages.rs index 72249e4f4e33..08f766e23686 100644 --- a/bridges/bin/runtime-common/src/messages.rs +++ b/bridges/bin/runtime-common/src/messages.rs @@ -37,6 +37,7 @@ use frame_support::{ RuntimeDebug, }; use hash_db::Hasher; +use scale_info::TypeInfo; use sp_runtime::{ traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul}, FixedPointNumber, FixedPointOperand, FixedU128, @@ -200,7 +201,7 @@ pub mod source { /// - hash of finalized header; /// - storage proof of inbound lane state; /// - lane id. - #[derive(Clone, Decode, Encode, Eq, PartialEq, RuntimeDebug)] + #[derive(Clone, Decode, Encode, Eq, PartialEq, RuntimeDebug, TypeInfo)] pub struct FromBridgedChainMessagesDeliveryProof { /// Hash of the bridge header the proof is for. pub bridged_header_hash: BridgedHeaderHash, @@ -431,7 +432,7 @@ pub mod target { /// - storage proof of messages and (optionally) outbound lane state; /// - lane id; /// - nonces (inclusive range) of messages which are included in this proof. - #[derive(Clone, Decode, Encode, Eq, PartialEq, RuntimeDebug)] + #[derive(Clone, Decode, Encode, Eq, PartialEq, RuntimeDebug, TypeInfo)] pub struct FromBridgedChainMessagesProof { /// Hash of the finalized bridged header the proof is for. pub bridged_header_hash: BridgedHeaderHash, diff --git a/bridges/fuzz/storage-proof/Cargo.toml b/bridges/fuzz/storage-proof/Cargo.toml index c5848ebed00e..43e58ddb73e9 100644 --- a/bridges/fuzz/storage-proof/Cargo.toml +++ b/bridges/fuzz/storage-proof/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0" } -finality-grandpa = "0.14.0" +finality-grandpa = "0.14.4" hash-db = "0.15.2" honggfuzz = "0.5.54" log = "0.4.0" diff --git a/bridges/modules/dispatch/Cargo.toml b/bridges/modules/dispatch/Cargo.toml index 6170af272ad9..fb601a70a1e2 100644 --- a/bridges/modules/dispatch/Cargo.toml +++ b/bridges/modules/dispatch/Cargo.toml @@ -8,6 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } log = { version = "0.4.14", default-features = false } # Bridge dependencies @@ -32,9 +33,11 @@ default = ["std"] std = [ "bp-message-dispatch/std", "bp-runtime/std", + "codec/std", "frame-support/std", "frame-system/std", "log/std", + "scale-info/std", "sp-core/std", "sp-runtime/std", "sp-std/std", diff --git a/bridges/modules/dispatch/src/lib.rs b/bridges/modules/dispatch/src/lib.rs index 8d089f330506..00858272365a 100644 --- a/bridges/modules/dispatch/src/lib.rs +++ b/bridges/modules/dispatch/src/lib.rs @@ -399,6 +399,7 @@ mod tests { use super::*; use frame_support::{dispatch::GetDispatchInfo, parameter_types, weights::Weight}; use frame_system::{EventRecord, Phase}; + use scale_info::TypeInfo; use sp_core::H256; use sp_runtime::{ testing::Header, @@ -412,7 +413,7 @@ mod tests { const SOURCE_CHAIN_ID: ChainId = *b"srce"; const TARGET_CHAIN_ID: ChainId = *b"trgt"; - #[derive(Debug, Encode, Decode, Clone, PartialEq, Eq)] + #[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo)] pub struct TestAccountPublic(AccountId); impl IdentifyAccount for TestAccountPublic { @@ -423,7 +424,7 @@ mod tests { } } - #[derive(Debug, Encode, Decode, Clone, PartialEq, Eq)] + #[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo)] pub struct TestSignature(AccountId); impl Verify for TestSignature { @@ -516,7 +517,7 @@ mod tests { impl Contains for TestCallFilter { fn contains(call: &Call) -> bool { - !matches!(*call, Call::System(frame_system::Call::fill_block(_))) + !matches!(*call, Call::System(frame_system::Call::fill_block { .. })) } } @@ -569,8 +570,9 @@ mod tests { let id = [0; 4]; const BAD_SPEC_VERSION: SpecVersion = 99; - let mut message = - prepare_root_message(Call::System(>::remark(vec![1, 2, 3]))); + let mut message = prepare_root_message(Call::System(frame_system::Call::::remark { + remark: vec![1, 2, 3], + })); let weight = message.weight; message.spec_version = BAD_SPEC_VERSION; @@ -599,7 +601,7 @@ mod tests { fn should_fail_on_weight_mismatch() { new_test_ext().execute_with(|| { let id = [0; 4]; - let call = Call::System(>::remark(vec![1, 2, 3])); + let call = Call::System(frame_system::Call::::remark { remark: vec![1, 2, 3] }); let call_weight = call.get_dispatch_info().weight; let mut message = prepare_root_message(call); message.weight = 7; @@ -637,7 +639,7 @@ mod tests { let call_origin = CallOrigin::TargetAccount(1, TestAccountPublic(1), TestSignature(99)); let message = prepare_message( call_origin, - Call::System(>::remark(vec![1, 2, 3])), + Call::System(frame_system::Call::::remark { remark: vec![1, 2, 3] }), ); let weight = message.weight; @@ -687,8 +689,9 @@ mod tests { new_test_ext().execute_with(|| { let id = [0; 4]; - let mut message = - prepare_root_message(Call::System(>::remark(vec![1, 2, 3]))); + let mut message = prepare_root_message(Call::System(frame_system::Call::::remark { + remark: vec![1, 2, 3], + })); let weight = message.weight; message.call.0 = vec![]; @@ -716,7 +719,9 @@ mod tests { new_test_ext().execute_with(|| { let id = [0; 4]; - let call = Call::System(>::fill_block(Perbill::from_percent(75))); + let call = Call::System(frame_system::Call::::fill_block { + ratio: Perbill::from_percent(75), + }); let weight = call.get_dispatch_info().weight; let mut message = prepare_root_message(call); message.weight = weight; @@ -745,8 +750,9 @@ mod tests { new_test_ext().execute_with(|| { let id = [0; 4]; - let mut message = - prepare_root_message(Call::System(>::remark(vec![1, 2, 3]))); + let mut message = prepare_root_message(Call::System(frame_system::Call::::remark { + remark: vec![1, 2, 3], + })); let weight = message.weight; message.dispatch_fee_payment = DispatchFeePayment::AtTargetChain; @@ -779,8 +785,9 @@ mod tests { new_test_ext().execute_with(|| { let id = [0; 4]; - let mut message = - prepare_root_message(Call::System(>::remark(vec![1, 2, 3]))); + let mut message = prepare_root_message(Call::System(frame_system::Call::::remark { + remark: vec![1, 2, 3], + })); message.dispatch_fee_payment = DispatchFeePayment::AtTargetChain; System::set_block_number(1); @@ -808,7 +815,7 @@ mod tests { new_test_ext().execute_with(|| { let id = [0; 4]; - let call = Call::System(>::set_heap_pages(1)); + let call = Call::System(frame_system::Call::::set_heap_pages { pages: 1 }); let message = prepare_target_message(call); System::set_block_number(1); @@ -835,7 +842,9 @@ mod tests { fn should_dispatch_bridge_message_from_root_origin() { new_test_ext().execute_with(|| { let id = [0; 4]; - let message = prepare_root_message(Call::System(>::remark(vec![1, 2, 3]))); + let message = prepare_root_message(Call::System(frame_system::Call::::remark { + remark: vec![1, 2, 3], + })); System::set_block_number(1); let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!()); @@ -862,7 +871,7 @@ mod tests { new_test_ext().execute_with(|| { let id = [0; 4]; - let call = Call::System(>::remark(vec![])); + let call = Call::System(frame_system::Call::::remark { remark: vec![] }); let message = prepare_target_message(call); System::set_block_number(1); @@ -890,7 +899,7 @@ mod tests { new_test_ext().execute_with(|| { let id = [0; 4]; - let call = Call::System(>::remark(vec![])); + let call = Call::System(frame_system::Call::::remark { remark: vec![] }); let message = prepare_source_message(call); System::set_block_number(1); @@ -915,7 +924,7 @@ mod tests { #[test] fn origin_is_checked_when_verifying_sending_message_using_source_root_account() { - let call = Call::System(>::remark(vec![])); + let call = Call::System(frame_system::Call::::remark { remark: vec![] }); let message = prepare_root_message(call); // When message is sent by Root, CallOrigin::SourceRoot is allowed @@ -930,7 +939,7 @@ mod tests { #[test] fn origin_is_checked_when_verifying_sending_message_using_target_account() { - let call = Call::System(>::remark(vec![])); + let call = Call::System(frame_system::Call::::remark { remark: vec![] }); let message = prepare_target_message(call); // When message is sent by Root, CallOrigin::TargetAccount is not allowed @@ -955,7 +964,7 @@ mod tests { #[test] fn origin_is_checked_when_verifying_sending_message_using_source_account() { - let call = Call::System(>::remark(vec![])); + let call = Call::System(frame_system::Call::::remark { remark: vec![] }); let message = prepare_source_message(call); // Sending a message from the expected origin account works diff --git a/bridges/modules/ethereum-contract-builtin/Cargo.toml b/bridges/modules/ethereum-contract-builtin/Cargo.toml index d20b0d0be85b..6177ed3734ca 100644 --- a/bridges/modules/ethereum-contract-builtin/Cargo.toml +++ b/bridges/modules/ethereum-contract-builtin/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0" } ethereum-types = "0.11.0" -finality-grandpa = "0.14.1" +finality-grandpa = "0.14.4" hex = "0.4" log = "0.4.14" diff --git a/bridges/modules/grandpa/Cargo.toml b/bridges/modules/grandpa/Cargo.toml index aa2e33cf447b..0347af07b77c 100644 --- a/bridges/modules/grandpa/Cargo.toml +++ b/bridges/modules/grandpa/Cargo.toml @@ -9,9 +9,10 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } -finality-grandpa = { version = "0.14.1", default-features = false } +finality-grandpa = { version = "0.14.4", default-features = false } log = { version = "0.4.14", default-features = false } num-traits = { version = "0.2", default-features = false } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } # Bridge Dependencies @@ -47,6 +48,7 @@ std = [ "frame-system/std", "log/std", "num-traits/std", + "scale-info/std", "serde", "sp-finality-grandpa/std", "sp-runtime/std", diff --git a/bridges/modules/messages/Cargo.toml b/bridges/modules/messages/Cargo.toml index a26cf65c028b..1d664e421695 100644 --- a/bridges/modules/messages/Cargo.toml +++ b/bridges/modules/messages/Cargo.toml @@ -11,6 +11,7 @@ bitvec = { version = "0.20", default-features = false, features = ["alloc"] } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } log = { version = "0.4.14", default-features = false } num-traits = { version = "0.2", default-features = false } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0.101", optional = true, features = ["derive"] } # Bridge dependencies @@ -47,6 +48,7 @@ std = [ "frame-system/std", "log/std", "num-traits/std", + "scale-info/std", "serde", "sp-core/std", "sp-runtime/std", diff --git a/bridges/modules/messages/src/mock.rs b/bridges/modules/messages/src/mock.rs index 4fc8d3ed6b17..35358b76f26d 100644 --- a/bridges/modules/messages/src/mock.rs +++ b/bridges/modules/messages/src/mock.rs @@ -32,6 +32,7 @@ use bp_messages::{ use bp_runtime::{messages::MessageDispatchResult, Size}; use codec::{Decode, Encode}; use frame_support::{parameter_types, weights::Weight}; +use scale_info::TypeInfo; use sp_core::H256; use sp_runtime::{ testing::Header as SubstrateHeader, @@ -42,7 +43,7 @@ use std::collections::BTreeMap; pub type AccountId = u64; pub type Balance = u64; -#[derive(Decode, Encode, Clone, Debug, PartialEq, Eq)] +#[derive(Decode, Encode, Clone, Debug, PartialEq, Eq, TypeInfo)] pub struct TestPayload { /// Field that may be used to identify messages. pub id: u64, @@ -138,7 +139,7 @@ parameter_types! { pub storage TokenConversionRate: FixedU128 = 1.into(); } -#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)] +#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq, TypeInfo)] pub enum TestMessagesParameter { TokenConversionRate(FixedU128), } @@ -211,7 +212,7 @@ pub const PAYLOAD_REJECTED_BY_TARGET_CHAIN: TestPayload = message_payload(1, 50) pub type MessagesByLaneVec = Vec<(LaneId, ProvedLaneMessages>)>; /// Test messages proof. -#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq)] +#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo)] pub struct TestMessagesProof { pub result: Result, } @@ -242,7 +243,7 @@ impl From>, ()>> for TestMessagesProof { } /// Messages delivery proof used in tests. -#[derive(Debug, Encode, Decode, Eq, Clone, PartialEq)] +#[derive(Debug, Encode, Decode, Eq, Clone, PartialEq, TypeInfo)] pub struct TestMessagesDeliveryProof(pub Result<(LaneId, InboundLaneData), ()>); impl Size for TestMessagesDeliveryProof { diff --git a/bridges/primitives/chain-millau/Cargo.toml b/bridges/primitives/chain-millau/Cargo.toml index 671bcbd53d00..3628f9092091 100644 --- a/bridges/primitives/chain-millau/Cargo.toml +++ b/bridges/primitives/chain-millau/Cargo.toml @@ -16,7 +16,7 @@ fixed-hash = { version = "0.7.0", default-features = false } hash256-std-hasher = { version = "0.15.2", default-features = false } impl-codec = { version = "0.5.1", default-features = false } impl-serde = { version = "0.3.1", optional = true } -parity-util-mem = { version = "0.9.0", default-features = false, features = ["primitive-types"] } +parity-util-mem = { version = "0.10.0", default-features = false, features = ["primitive-types"] } serde = { version = "1.0.101", optional = true, features = ["derive"] } # Substrate Based Dependencies diff --git a/bridges/primitives/header-chain/Cargo.toml b/bridges/primitives/header-chain/Cargo.toml index 844e59865202..e64a54a1ad20 100644 --- a/bridges/primitives/header-chain/Cargo.toml +++ b/bridges/primitives/header-chain/Cargo.toml @@ -8,7 +8,8 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } -finality-grandpa = { version = "0.14.1", default-features = false } +finality-grandpa = { version = "0.14.4", default-features = false } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } # Substrate Dependencies @@ -28,6 +29,7 @@ default = ["std"] std = [ "codec/std", "finality-grandpa/std", + "scale-info/std", "serde/std", "frame-support/std", "sp-core/std", diff --git a/bridges/primitives/header-chain/src/justification.rs b/bridges/primitives/header-chain/src/justification.rs index cc47070b8ca2..fc7256481068 100644 --- a/bridges/primitives/header-chain/src/justification.rs +++ b/bridges/primitives/header-chain/src/justification.rs @@ -22,6 +22,7 @@ use codec::{Decode, Encode}; use finality_grandpa::voter_set::VoterSet; use frame_support::RuntimeDebug; +use scale_info::TypeInfo; use sp_finality_grandpa::{AuthorityId, AuthoritySignature, SetId}; use sp_runtime::traits::Header as HeaderT; use sp_std::collections::{btree_map::BTreeMap, btree_set::BTreeSet}; @@ -32,7 +33,7 @@ use sp_std::prelude::*; /// /// This particular proof is used to prove that headers on a bridged chain /// (so not our chain) have been finalized correctly. -#[derive(Encode, Decode, RuntimeDebug, Clone, PartialEq, Eq)] +#[derive(Encode, Decode, RuntimeDebug, Clone, PartialEq, Eq, TypeInfo)] pub struct GrandpaJustification { /// The round (voting period) this justification is valid for. pub round: u64, diff --git a/bridges/primitives/header-chain/src/lib.rs b/bridges/primitives/header-chain/src/lib.rs index adac6eb26880..16511e99f79e 100644 --- a/bridges/primitives/header-chain/src/lib.rs +++ b/bridges/primitives/header-chain/src/lib.rs @@ -24,6 +24,7 @@ use core::clone::Clone; use core::cmp::Eq; use core::default::Default; use core::fmt::Debug; +use scale_info::TypeInfo; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; use sp_finality_grandpa::{AuthorityList, ConsensusLog, SetId, GRANDPA_ENGINE_ID}; @@ -39,7 +40,7 @@ pub trait Parameter: Codec + EncodeLike + Clone + Eq + Debug {} impl Parameter for T where T: Codec + EncodeLike + Clone + Eq + Debug {} /// A GRANDPA Authority List and ID. -#[derive(Default, Encode, Decode, RuntimeDebug, PartialEq, Clone)] +#[derive(Default, Encode, Decode, RuntimeDebug, PartialEq, Clone, TypeInfo)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct AuthoritySet { /// List of GRANDPA authorities for the current round. @@ -58,7 +59,7 @@ impl AuthoritySet { /// Data required for initializing the bridge pallet. /// /// The bridge needs to know where to start its sync from, and this provides that initial context. -#[derive(Default, Encode, Decode, RuntimeDebug, PartialEq, Eq, Clone)] +#[derive(Default, Encode, Decode, RuntimeDebug, PartialEq, Eq, Clone, TypeInfo)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct InitializationData { /// The header from which we should start syncing. diff --git a/bridges/primitives/message-dispatch/Cargo.toml b/bridges/primitives/message-dispatch/Cargo.toml index 84fa48553a21..9b24ae86a067 100644 --- a/bridges/primitives/message-dispatch/Cargo.toml +++ b/bridges/primitives/message-dispatch/Cargo.toml @@ -9,6 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] bp-runtime = { path = "../runtime", default-features = false } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } # Substrate Dependencies @@ -21,5 +22,6 @@ std = [ "bp-runtime/std", "codec/std", "frame-support/std", + "scale-info/std", "sp-std/std", ] diff --git a/bridges/primitives/message-dispatch/src/lib.rs b/bridges/primitives/message-dispatch/src/lib.rs index 859dc5e469ad..b2683674b776 100644 --- a/bridges/primitives/message-dispatch/src/lib.rs +++ b/bridges/primitives/message-dispatch/src/lib.rs @@ -25,6 +25,7 @@ use bp_runtime::{ }; use codec::{Decode, Encode}; use frame_support::RuntimeDebug; +use scale_info::TypeInfo; use sp_std::prelude::*; /// Message dispatch weight. @@ -71,7 +72,7 @@ pub trait MessageDispatch { /// The source chain can (and should) verify that the message can be dispatched on the target chain /// with a particular origin given the source chain's origin. This can be done with the /// `verify_message_origin()` function. -#[derive(RuntimeDebug, Encode, Decode, Clone, PartialEq, Eq)] +#[derive(RuntimeDebug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo)] pub enum CallOrigin { /// Call is sent by the Root origin on the source chain. On the target chain it is dispatched /// from a derived account. @@ -111,7 +112,7 @@ pub enum CallOrigin { /// Runtime specification version. We only dispatch messages that have the same /// runtime version. Otherwise we risk to misinterpret encoded calls. diff --git a/bridges/primitives/messages/Cargo.toml b/bridges/primitives/messages/Cargo.toml index b5b68220a409..191742005f44 100644 --- a/bridges/primitives/messages/Cargo.toml +++ b/bridges/primitives/messages/Cargo.toml @@ -10,6 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" bitvec = { version = "0.20", default-features = false, features = ["alloc"] } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive", "bit-vec"] } impl-trait-for-tuples = "0.2" +scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0.101", optional = true, features = ["derive"] } # Bridge dependencies @@ -29,6 +30,7 @@ std = [ "codec/std", "frame-support/std", "frame-system/std", + "scale-info/std", "serde", - "sp-std/std" + "sp-std/std", ] diff --git a/bridges/primitives/messages/src/lib.rs b/bridges/primitives/messages/src/lib.rs index 963543ec3213..344735b53c91 100644 --- a/bridges/primitives/messages/src/lib.rs +++ b/bridges/primitives/messages/src/lib.rs @@ -26,6 +26,7 @@ use bitvec::prelude::*; use bp_runtime::messages::DispatchFeePayment; use codec::{Decode, Encode}; use frame_support::RuntimeDebug; +use scale_info::TypeInfo; use sp_std::{collections::vec_deque::VecDeque, prelude::*}; pub mod source_chain; @@ -35,7 +36,7 @@ pub mod target_chain; pub use frame_support::weights::Weight; /// Messages pallet operating mode. -#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug)] +#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo)] #[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] pub enum OperatingMode { /// Normal mode, when all operations are allowed. @@ -81,7 +82,7 @@ pub type MessageId = (LaneId, MessageNonce); pub type MessagePayload = Vec; /// Message key (unique message identifier) as it is stored in the storage. -#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] pub struct MessageKey { /// ID of the message lane. pub lane_id: LaneId, @@ -90,7 +91,7 @@ pub struct MessageKey { } /// Message data as it is stored in the storage. -#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] pub struct MessageData { /// Message payload. pub payload: MessagePayload, @@ -99,7 +100,7 @@ pub struct MessageData { } /// Message as it is stored in the storage. -#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] pub struct Message { /// Message key. pub key: MessageKey, @@ -108,7 +109,7 @@ pub struct Message { } /// Inbound lane data. -#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] +#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq, TypeInfo)] pub struct InboundLaneData { /// Identifiers of relayers and messages that they have delivered to this lane (ordered by message nonce). /// @@ -195,7 +196,7 @@ pub type DispatchResultsBitVec = BitVec; /// /// This struct represents a continuous range of messages that have been delivered by the same relayer /// and whose confirmations are still pending. -#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] +#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq, TypeInfo)] pub struct UnrewardedRelayer { /// Identifier of the relayer. pub relayer: RelayerId, @@ -204,7 +205,7 @@ pub struct UnrewardedRelayer { } /// Delivered messages with their dispatch result. -#[derive(Clone, Default, Encode, Decode, RuntimeDebug, PartialEq, Eq)] +#[derive(Clone, Default, Encode, Decode, RuntimeDebug, PartialEq, Eq, TypeInfo)] pub struct DeliveredMessages { /// Nonce of the first message that has been delivered (inclusive). pub begin: MessageNonce, @@ -254,7 +255,7 @@ impl DeliveredMessages { } /// Gist of `InboundLaneData::relayers` field used by runtime APIs. -#[derive(Clone, Default, Encode, Decode, RuntimeDebug, PartialEq, Eq)] +#[derive(Clone, Default, Encode, Decode, RuntimeDebug, PartialEq, Eq, TypeInfo)] pub struct UnrewardedRelayersState { /// Number of entries in the `InboundLaneData::relayers` set. pub unrewarded_relayer_entries: MessageNonce, @@ -266,7 +267,7 @@ pub struct UnrewardedRelayersState { } /// Outbound lane data. -#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] +#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq, TypeInfo)] pub struct OutboundLaneData { /// Nonce of oldest message that we haven't yet pruned. May point to not-yet-generated message if /// all sent messages are already pruned. diff --git a/bridges/primitives/messages/src/target_chain.rs b/bridges/primitives/messages/src/target_chain.rs index d1b87fd02323..873059763791 100644 --- a/bridges/primitives/messages/src/target_chain.rs +++ b/bridges/primitives/messages/src/target_chain.rs @@ -21,13 +21,14 @@ use crate::{LaneId, Message, MessageData, MessageKey, OutboundLaneData}; use bp_runtime::{messages::MessageDispatchResult, Size}; use codec::{Decode, Encode, Error as CodecError}; use frame_support::{weights::Weight, Parameter, RuntimeDebug}; +use scale_info::TypeInfo; use sp_std::{collections::btree_map::BTreeMap, fmt::Debug, prelude::*}; /// Proved messages from the source chain. pub type ProvedMessages = BTreeMap>; /// Proved messages from single lane of the source chain. -#[derive(RuntimeDebug, Encode, Decode, Clone, PartialEq, Eq)] +#[derive(RuntimeDebug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo)] pub struct ProvedLaneMessages { /// Optional outbound lane state. pub lane_state: Option, diff --git a/bridges/primitives/polkadot-core/Cargo.toml b/bridges/primitives/polkadot-core/Cargo.toml index 995f948e5d47..5e95c223ce2e 100644 --- a/bridges/primitives/polkadot-core/Cargo.toml +++ b/bridges/primitives/polkadot-core/Cargo.toml @@ -8,6 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] parity-scale-codec = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } # Bridge Dependencies @@ -35,6 +36,7 @@ std = [ "frame-support/std", "frame-system/std", "parity-scale-codec/std", + "scale-info/std", "sp-api/std", "sp-core/std", "sp-runtime/std", diff --git a/bridges/primitives/polkadot-core/src/lib.rs b/bridges/primitives/polkadot-core/src/lib.rs index a1619b27bcf4..151e374e6603 100644 --- a/bridges/primitives/polkadot-core/src/lib.rs +++ b/bridges/primitives/polkadot-core/src/lib.rs @@ -213,7 +213,7 @@ pub type AdditionalSigned = (u32, u32, Hash, Hash, (), (), ()); /// A simplified version of signed extensions meant for producing signed transactions /// and signed payload in the client code. -#[derive(PartialEq, Eq, Clone, RuntimeDebug)] +#[derive(PartialEq, Eq, Clone, RuntimeDebug, scale_info::TypeInfo)] pub struct SignedExtensions { encode_payload: SignedExtra, additional_signed: AdditionalSigned, @@ -266,7 +266,14 @@ impl SignedExtensions { impl sp_runtime::traits::SignedExtension for SignedExtensions where - Call: parity_scale_codec::Codec + sp_std::fmt::Debug + Sync + Send + Clone + Eq + PartialEq, + Call: parity_scale_codec::Codec + + sp_std::fmt::Debug + + Sync + + Send + + Clone + + Eq + + PartialEq + + scale_info::StaticTypeInfo, Call: Dispatchable, { const IDENTIFIER: &'static str = "Not needed."; diff --git a/bridges/primitives/runtime/Cargo.toml b/bridges/primitives/runtime/Cargo.toml index 17fa96b2c908..cdd47e30d3f8 100644 --- a/bridges/primitives/runtime/Cargo.toml +++ b/bridges/primitives/runtime/Cargo.toml @@ -10,6 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } hash-db = { version = "0.15.2", default-features = false } num-traits = { version = "0.2", default-features = false } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } # Substrate Dependencies @@ -32,6 +33,7 @@ std = [ "frame-support/std", "hash-db/std", "num-traits/std", + "scale-info/std", "sp-core/std", "sp-io/std", "sp-runtime/std", diff --git a/bridges/primitives/runtime/src/messages.rs b/bridges/primitives/runtime/src/messages.rs index f6e04619c723..3ab867773f9f 100644 --- a/bridges/primitives/runtime/src/messages.rs +++ b/bridges/primitives/runtime/src/messages.rs @@ -18,9 +18,10 @@ use codec::{Decode, Encode}; use frame_support::{weights::Weight, RuntimeDebug}; +use scale_info::TypeInfo; /// Where message dispatch fee is paid? -#[derive(Encode, Decode, RuntimeDebug, Clone, Copy, PartialEq, Eq)] +#[derive(Encode, Decode, RuntimeDebug, Clone, Copy, PartialEq, Eq, TypeInfo)] pub enum DispatchFeePayment { /// The dispacth fee is paid at the source chain. AtSourceChain, @@ -34,7 +35,7 @@ pub enum DispatchFeePayment { } /// Message dispatch result. -#[derive(Encode, Decode, RuntimeDebug, Clone, PartialEq, Eq)] +#[derive(Encode, Decode, RuntimeDebug, Clone, PartialEq, Eq, TypeInfo)] pub struct MessageDispatchResult { /// Dispatch result flag. This flag is relayed back to the source chain and, generally /// speaking, may bring any (that fits in single bit) information from the dispatcher at diff --git a/bridges/primitives/test-utils/Cargo.toml b/bridges/primitives/test-utils/Cargo.toml index fe6a68087873..14d3c031b4c8 100644 --- a/bridges/primitives/test-utils/Cargo.toml +++ b/bridges/primitives/test-utils/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" bp-header-chain = { path = "../header-chain", default-features = false } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } ed25519-dalek = { version = "1.0", default-features = false, features = ["u64_backend"] } -finality-grandpa = { version = "0.14.1", default-features = false } +finality-grandpa = { version = "0.14.4", default-features = false } sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } diff --git a/bridges/relays/bin-substrate/Cargo.toml b/bridges/relays/bin-substrate/Cargo.toml index c2f30546f30f..830f592ec4e1 100644 --- a/bridges/relays/bin-substrate/Cargo.toml +++ b/bridges/relays/bin-substrate/Cargo.toml @@ -32,7 +32,7 @@ bp-wococo = { path = "../../primitives/chain-wococo" } bp-runtime = { path = "../../primitives/runtime" } bp-westend = { path = "../../primitives/chain-westend" } bridge-runtime-common = { path = "../../bin/runtime-common" } -finality-grandpa = { version = "0.14.1" } +finality-grandpa = { version = "0.14.1", } finality-relay = { path = "../finality" } headers-relay = { path = "../headers" } messages-relay = { path = "../messages" } diff --git a/core-primitives/Cargo.toml b/core-primitives/Cargo.toml index e40196ec559f..9b469657bde1 100644 --- a/core-primitives/Cargo.toml +++ b/core-primitives/Cargo.toml @@ -8,15 +8,18 @@ edition = "2018" sp-core = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } parity-scale-codec = { version = "2.0.0", default-features = false, features = [ "derive" ] } parity-util-mem = { version = "0.10.0", default-features = false, optional = true } [features] default = [ "std" ] std = [ + "scale-info/std", "sp-core/std", "sp-runtime/std", "sp-std/std", + "scale-info/std", "parity-scale-codec/std", "parity-util-mem", ] diff --git a/core-primitives/src/lib.rs b/core-primitives/src/lib.rs index f0313b95d0d1..c00548e57c3c 100644 --- a/core-primitives/src/lib.rs +++ b/core-primitives/src/lib.rs @@ -23,6 +23,7 @@ use parity_scale_codec::{Decode, Encode}; #[cfg(feature = "std")] use parity_util_mem::MallocSizeOf; +use scale_info::TypeInfo; use sp_runtime::{ generic, traits::{IdentifyAccount, Verify}, @@ -64,7 +65,7 @@ pub type Hash = sp_core::H256; /// This type is produced by [`CandidateReceipt::hash`]. /// /// This type makes it easy to enforce that a hash is a candidate hash on the type level. -#[derive(Clone, Copy, Encode, Decode, Hash, Eq, PartialEq, Default, PartialOrd, Ord)] +#[derive(Clone, Copy, Encode, Decode, Hash, Eq, PartialEq, Default, PartialOrd, Ord, TypeInfo)] #[cfg_attr(feature = "std", derive(MallocSizeOf))] pub struct CandidateHash(pub Hash); @@ -117,7 +118,7 @@ pub type DownwardMessage = sp_std::vec::Vec; /// A wrapped version of `DownwardMessage`. The difference is that it has attached the block number when /// the message was sent. -#[derive(Encode, Decode, Clone, sp_runtime::RuntimeDebug, PartialEq)] +#[derive(Encode, Decode, Clone, sp_runtime::RuntimeDebug, PartialEq, TypeInfo)] #[cfg_attr(feature = "std", derive(MallocSizeOf))] pub struct InboundDownwardMessage { /// The block number at which these messages were put into the downward message queue. @@ -127,7 +128,7 @@ pub struct InboundDownwardMessage { } /// An HRMP message seen from the perspective of a recipient. -#[derive(Encode, Decode, Clone, sp_runtime::RuntimeDebug, PartialEq)] +#[derive(Encode, Decode, Clone, sp_runtime::RuntimeDebug, PartialEq, TypeInfo)] #[cfg_attr(feature = "std", derive(MallocSizeOf))] pub struct InboundHrmpMessage { /// The block number at which this message was sent. @@ -139,7 +140,7 @@ pub struct InboundHrmpMessage { } /// An HRMP message seen from the perspective of a sender. -#[derive(Encode, Decode, Clone, sp_runtime::RuntimeDebug, PartialEq, Eq, Hash)] +#[derive(Encode, Decode, Clone, sp_runtime::RuntimeDebug, PartialEq, Eq, Hash, TypeInfo)] #[cfg_attr(feature = "std", derive(MallocSizeOf))] pub struct OutboundHrmpMessage { /// The para that will get this message in its downward message queue. diff --git a/node/core/approval-voting/src/lib.rs b/node/core/approval-voting/src/lib.rs index 529523b5b8f9..b7588710b1a3 100644 --- a/node/core/approval-voting/src/lib.rs +++ b/node/core/approval-voting/src/lib.rs @@ -694,6 +694,7 @@ where woken_block, woken_candidate, tick, + &subsystem.metrics, )? } next_msg = ctx.recv().fuse() => { @@ -1063,7 +1064,7 @@ async fn handle_from_overseer( Ok(block_imported_candidates) => { // Schedule wakeups for all imported candidates. for block_batch in block_imported_candidates { - tracing::debug!( + tracing::trace!( target: LOG_TARGET, block_hash = ?block_batch.block_hash, num_candidates = block_batch.imported_candidates.len(), @@ -1710,14 +1711,14 @@ fn check_and_import_approval( None }; - let mut actions = import_checked_approval( + let mut actions = advance_approval_state( state, db, &metrics, block_entry, approved_candidate_hash, candidate_entry, - ApprovalSource::Remote(approval.validator), + ApprovalStateTransition::RemoteApproval(approval.validator), ); actions.extend(inform_disputes_action); @@ -1725,41 +1726,46 @@ fn check_and_import_approval( Ok((actions, t)) } -enum ApprovalSource { - Remote(ValidatorIndex), - Local(ValidatorIndex, ValidatorSignature), +#[derive(Debug)] +enum ApprovalStateTransition { + RemoteApproval(ValidatorIndex), + LocalApproval(ValidatorIndex, ValidatorSignature), + WakeupProcessed, } -impl ApprovalSource { - fn validator_index(&self) -> ValidatorIndex { +impl ApprovalStateTransition { + fn validator_index(&self) -> Option { match *self { - ApprovalSource::Remote(v) | ApprovalSource::Local(v, _) => v, + ApprovalStateTransition::RemoteApproval(v) | + ApprovalStateTransition::LocalApproval(v, _) => Some(v), + ApprovalStateTransition::WakeupProcessed => None, } } - fn is_remote(&self) -> bool { + fn is_local_approval(&self) -> bool { match *self { - ApprovalSource::Remote(_) => true, - ApprovalSource::Local(_, _) => false, + ApprovalStateTransition::RemoteApproval(_) => false, + ApprovalStateTransition::LocalApproval(_, _) => true, + ApprovalStateTransition::WakeupProcessed => false, } } } -// Import an approval vote which is already checked to be valid and corresponding to an assigned -// validator on the candidate and block. This updates the block entry and candidate entry as +// Advance the approval state, either by importing an approval vote which is already checked to be valid and corresponding to an assigned +// validator on the candidate and block, or by noting that there are no further wakeups or tranches needed. This updates the block entry and candidate entry as // necessary and schedules any further wakeups. -fn import_checked_approval( +fn advance_approval_state( state: &State, db: &mut OverlayedBackend<'_, impl Backend>, metrics: &Metrics, mut block_entry: BlockEntry, candidate_hash: CandidateHash, mut candidate_entry: CandidateEntry, - source: ApprovalSource, + transition: ApprovalStateTransition, ) -> Vec { - let validator_index = source.validator_index(); + let validator_index = transition.validator_index(); - let already_approved_by = candidate_entry.mark_approval(validator_index); + let already_approved_by = validator_index.as_ref().map(|v| candidate_entry.mark_approval(*v)); let candidate_approved_in_block = block_entry.is_candidate_approved(&candidate_hash); // Check for early exits. @@ -1771,17 +1777,13 @@ fn import_checked_approval( // If the block was approved, but the validator hadn't approved it yet, we should still hold // onto the approval vote on-disk in case we restart and rebroadcast votes. Otherwise, our // assignment might manifest as a no-show. - match source { - ApprovalSource::Remote(_) => { - // We don't store remote votes, so we can early exit as long at the candidate is - // already concluded under the block i.e. we don't need more approvals. - if candidate_approved_in_block { - return Vec::new() - } - }, - ApprovalSource::Local(_, _) => { - // We never early return on the local validator. - }, + if !transition.is_local_approval() { + // We don't store remote votes and there's nothing to store for processed wakeups, + // so we can early exit as long at the candidate is already concluded under the + // block i.e. we don't need more approvals. + if candidate_approved_in_block { + return Vec::new() + } } let mut actions = Vec::new(); @@ -1852,7 +1854,7 @@ fn import_checked_approval( approval_entry.mark_approved(); } - if let ApprovalSource::Local(_, ref sig) = source { + if let ApprovalStateTransition::LocalApproval(_, ref sig) = transition { approval_entry.import_approval_sig(sig.clone()); } @@ -1865,13 +1867,15 @@ fn import_checked_approval( status.required_tranches, )); - // We have no need to write the candidate entry if + // We have no need to write the candidate entry if all of the following + // is true: // - // 1. The source is remote, as we don't store anything new in the approval entry. + // 1. This is not a local approval, as we don't store anything new in the approval entry. // 2. The candidate is not newly approved, as we haven't altered the approval entry's // approved flag with `mark_approved` above. - // 3. The source had already approved the candidate, as we haven't altered the bitfield. - if !source.is_remote() || newly_approved || !already_approved_by { + // 3. The approver, if any, had already approved the candidate, as we haven't altered the bitfield. + if transition.is_local_approval() || newly_approved || !already_approved_by.unwrap_or(true) + { // In all other cases, we need to write the candidate entry. db.write_candidate_entry(candidate_entry); } @@ -1918,6 +1922,7 @@ fn process_wakeup( relay_block: Hash, candidate_hash: CandidateHash, expected_tick: Tick, + metrics: &Metrics, ) -> SubsystemResult> { let _span = jaeger::Span::from_encodable( (relay_block, candidate_hash, expected_tick), @@ -2040,28 +2045,20 @@ fn process_wakeup( } } - let approval_entry = candidate_entry - .approval_entry(&relay_block) - .expect("this function returned earlier if not available; qed"); - - // Although we ran this earlier in the function, we need to run again because we might have - // imported our own assignment, which could change things. - let tranches_to_approve = approval_checking::tranches_to_approve( - &approval_entry, - candidate_entry.approvals(), - tranche_now, - block_tick, - no_show_duration, - session_info.needed_approvals as _, - ); - - actions.extend(schedule_wakeup_action( - &approval_entry, - relay_block, - block_entry.block_number(), + // Although we checked approval earlier in this function, + // this wakeup might have advanced the state to approved via + // a no-show that was immediately covered and therefore + // we need to check for that and advance the state on-disk. + // + // Note that this function also schedules a wakeup as necessary. + actions.extend(advance_approval_state( + state, + db, + metrics, + block_entry, candidate_hash, - block_tick, - tranches_to_approve, + candidate_entry, + ApprovalStateTransition::WakeupProcessed, )); Ok(actions) @@ -2410,7 +2407,7 @@ async fn issue_approval( ) .expect("Statement just signed; should pass checks; qed"); - tracing::debug!( + tracing::trace!( target: LOG_TARGET, ?candidate_hash, ?block_hash, @@ -2436,14 +2433,14 @@ async fn issue_approval( None }; - let mut actions = import_checked_approval( + let mut actions = advance_approval_state( state, db, metrics, block_entry, candidate_hash, candidate_entry, - ApprovalSource::Local(validator_index as _, sig.clone()), + ApprovalStateTransition::LocalApproval(validator_index as _, sig.clone()), ); metrics.on_approval_produced(); diff --git a/node/core/approval-voting/src/tests.rs b/node/core/approval-voting/src/tests.rs index 9819991641c5..c40d62ecedf1 100644 --- a/node/core/approval-voting/src/tests.rs +++ b/node/core/approval-voting/src/tests.rs @@ -2555,3 +2555,197 @@ fn subsystem_assignment_not_triggered_if_at_maximum_but_clock_is_before_with_dri should_be_triggered: |_| false, }); } + +#[test] +fn pre_covers_dont_stall_approval() { + // A, B are tranche 0. + // C is tranche 1. + // + // All assignments imported at once, and B, C approvals imported immediately. + // A no-shows, leading to being covered by C. + // Technically, this is an approved block, but it will be approved + // when the no-show timer hits, not as a response to an approval vote. + // + // Note that we have 6 validators, otherwise the 2nd approval triggers + // the >1/3 insta-approval condition. + + let assignment_criteria = Box::new(MockAssignmentCriteria::check_only( + move |validator_index| match validator_index { + ValidatorIndex(0 | 1) => Ok(0), + ValidatorIndex(2) => Ok(1), + ValidatorIndex(_) => Err(criteria::InvalidAssignment), + }, + )); + + let config = HarnessConfigBuilder::default().assignment_criteria(assignment_criteria).build(); + let store = config.backend(); + test_harness(config, |test_harness| async move { + let TestHarness { + mut virtual_overseer, + clock, + sync_oracle_handle: _sync_oracle_handle, + .. + } = test_harness; + + let block_hash = Hash::repeat_byte(0x01); + let validator_index_a = ValidatorIndex(0); + let validator_index_b = ValidatorIndex(1); + let validator_index_c = ValidatorIndex(2); + + let validators = vec![ + Sr25519Keyring::Alice, + Sr25519Keyring::Bob, + Sr25519Keyring::Charlie, + Sr25519Keyring::Dave, + Sr25519Keyring::Eve, + Sr25519Keyring::One, + ]; + let session_info = SessionInfo { + validators: validators.iter().map(|v| v.public().into()).collect(), + validator_groups: vec![ + vec![ValidatorIndex(0), ValidatorIndex(1)], + vec![ValidatorIndex(2), ValidatorIndex(5)], + vec![ValidatorIndex(3), ValidatorIndex(4)], + ], + needed_approvals: 2, + discovery_keys: validators.iter().map(|v| v.public().into()).collect(), + assignment_keys: validators.iter().map(|v| v.public().into()).collect(), + n_cores: validators.len() as _, + zeroth_delay_tranche_width: 5, + relay_vrf_modulo_samples: 3, + n_delay_tranches: 50, + no_show_slots: 2, + }; + + let candidate_descriptor = make_candidate(1.into(), &block_hash); + let candidate_hash = candidate_descriptor.hash(); + + let head: Hash = ChainBuilder::GENESIS_HASH; + let mut builder = ChainBuilder::new(); + let slot = Slot::from(1 as u64); + builder.add_block( + block_hash, + head, + 1, + BlockConfig { + slot, + candidates: Some(vec![(candidate_descriptor, CoreIndex(0), GroupIndex(0))]), + session_info: Some(session_info), + }, + ); + builder.build(&mut virtual_overseer).await; + + let candidate_index = 0; + + let rx = check_and_import_assignment( + &mut virtual_overseer, + block_hash, + candidate_index, + validator_index_a, + ) + .await; + + assert_eq!(rx.await, Ok(AssignmentCheckResult::Accepted),); + + let rx = check_and_import_assignment( + &mut virtual_overseer, + block_hash, + candidate_index, + validator_index_b, + ) + .await; + + assert_eq!(rx.await, Ok(AssignmentCheckResult::Accepted),); + + let rx = check_and_import_assignment( + &mut virtual_overseer, + block_hash, + candidate_index, + validator_index_c, + ) + .await; + + assert_eq!(rx.await, Ok(AssignmentCheckResult::Accepted),); + + let session_index = 1; + let sig_b = sign_approval(Sr25519Keyring::Bob, candidate_hash, session_index); + + let rx = check_and_import_approval( + &mut virtual_overseer, + block_hash, + candidate_index, + validator_index_b, + candidate_hash, + session_index, + false, + true, + Some(sig_b), + ) + .await; + + assert_eq!(rx.await, Ok(ApprovalCheckResult::Accepted),); + + let sig_c = sign_approval(Sr25519Keyring::Charlie, candidate_hash, session_index); + let rx = check_and_import_approval( + &mut virtual_overseer, + block_hash, + candidate_index, + validator_index_c, + candidate_hash, + session_index, + false, + true, + Some(sig_c), + ) + .await; + + assert_eq!(rx.await, Ok(ApprovalCheckResult::Accepted),); + + // Sleep to ensure we get a consistent read on the database. + // + // NOTE: Since the response above occurs before writing to the database, we are somewhat + // breaking the external consistency of the API by reaching into the database directly. + // Under normal operation, this wouldn't be necessary, since all requests are serialized by + // the event loop and we write at the end of each pass. However, if the database write were + // to fail, a downstream subsystem may expect for this candidate to be approved, and + // possibly take further actions on the assumption that the candidate is approved, when + // that may not be the reality from the database's perspective. This could be avoided + // entirely by having replies processed after database writes, but that would constitute a + // larger refactor and incur a performance penalty. + futures_timer::Delay::new(Duration::from_millis(100)).await; + + // The candidate should not be approved. + let candidate_entry = store.load_candidate_entry(&candidate_hash).unwrap().unwrap(); + assert!(!candidate_entry.approval_entry(&block_hash).unwrap().is_approved()); + assert!(clock.inner.lock().has_wakeup(20)); + + // Wait for the no-show timer to observe the approval from + // tranche 0 and set a wakeup for tranche 1. + clock.inner.lock().set_tick(20); + + // Sleep to ensure we get a consistent read on the database. + futures_timer::Delay::new(Duration::from_millis(100)).await; + + // The next wakeup should observe the assignment & approval from + // tranche 1, and the no-show from tranche 0 should be immediately covered. + assert_eq!(clock.inner.lock().next_wakeup(), Some(31)); + clock.inner.lock().set_tick(31); + + assert_matches!( + overseer_recv(&mut virtual_overseer).await, + AllMessages::ChainSelection(ChainSelectionMessage::Approved(b_hash)) => { + assert_eq!(b_hash, block_hash); + } + ); + + // The candidate and block should now be approved. + let candidate_entry = store.load_candidate_entry(&candidate_hash).unwrap().unwrap(); + assert!(candidate_entry.approval_entry(&block_hash).unwrap().is_approved()); + assert!(clock.inner.lock().next_wakeup().is_none()); + + let block_entry = store.load_block_entry(&block_hash).unwrap().unwrap(); + assert!(block_entry.is_fully_approved()); + + virtual_overseer + }); +} diff --git a/node/core/dispute-coordinator/src/dummy.rs b/node/core/dispute-coordinator/src/dummy.rs index eb3dfe28ca5b..afdf8951fd9c 100644 --- a/node/core/dispute-coordinator/src/dummy.rs +++ b/node/core/dispute-coordinator/src/dummy.rs @@ -31,6 +31,8 @@ use parity_scale_codec::{Decode, Encode, Error as CodecError}; use polkadot_node_subsystem_util::metrics::{self, prometheus}; use sc_keystore::LocalKeystore; +use crate::metrics::Metrics; + const LOG_TARGET: &str = "parachain::dispute-coordinator"; /// Candidate validation metrics placeholder. diff --git a/node/core/dispute-coordinator/src/lib.rs b/node/core/dispute-coordinator/src/lib.rs index a99be737de28..38e4f5d66d47 100644 --- a/node/core/dispute-coordinator/src/lib.rs +++ b/node/core/dispute-coordinator/src/lib.rs @@ -25,6 +25,8 @@ //! another node, this will trigger the dispute participation subsystem to recover and validate the block and call //! back to this subsystem. +mod metrics; + #[cfg(feature = "disputes")] mod real; #[cfg(feature = "disputes")] diff --git a/node/core/dispute-coordinator/src/metrics.rs b/node/core/dispute-coordinator/src/metrics.rs new file mode 100644 index 000000000000..b70ec09db976 --- /dev/null +++ b/node/core/dispute-coordinator/src/metrics.rs @@ -0,0 +1,99 @@ +// Copyright 2020 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +use polkadot_node_subsystem_util::metrics::{self, prometheus}; + +#[derive(Clone)] +struct MetricsInner { + /// Number of opened disputes. + open: prometheus::Counter, + /// Votes of all disputes. + votes: prometheus::CounterVec, + /// Conclusion across all disputes. + concluded: prometheus::CounterVec, +} + +/// Candidate validation metrics. +#[derive(Default, Clone)] +pub struct Metrics(Option); + +#[cfg(feature = "disputes")] +impl Metrics { + pub(crate) fn on_open(&self) { + if let Some(metrics) = &self.0 { + metrics.open.inc(); + } + } + + pub(crate) fn on_valid_vote(&self) { + if let Some(metrics) = &self.0 { + metrics.votes.with_label_values(&["valid"]).inc(); + } + } + + pub(crate) fn on_invalid_vote(&self) { + if let Some(metrics) = &self.0 { + metrics.votes.with_label_values(&["invalid"]).inc(); + } + } + + pub(crate) fn on_concluded_valid(&self) { + if let Some(metrics) = &self.0 { + metrics.concluded.with_label_values(&["valid"]).inc(); + } + } + + pub(crate) fn on_concluded_invalid(&self) { + if let Some(metrics) = &self.0 { + metrics.concluded.with_label_values(&["invalid"]).inc(); + } + } +} + +impl metrics::Metrics for Metrics { + fn try_register(registry: &prometheus::Registry) -> Result { + let metrics = MetricsInner { + open: prometheus::register( + prometheus::Counter::with_opts(prometheus::Opts::new( + "parachain_candidate_disputes_total", + "Total number of raised disputes.", + ))?, + registry, + )?, + concluded: prometheus::register( + prometheus::CounterVec::new( + prometheus::Opts::new( + "parachain_candidate_dispute_concluded", + "Concluded dispute votes, sorted by candidate is `valid` and `invalid`.", + ), + &["validity"], + )?, + registry, + )?, + votes: prometheus::register( + prometheus::CounterVec::new( + prometheus::Opts::new( + "parachain_candidate_dispute_votes", + "Accumulated dispute votes, sorted by candidate is `valid` and `invalid`.", + ), + &["validity"], + )?, + registry, + )?, + }; + Ok(Metrics(Some(metrics))) + } +} diff --git a/node/core/dispute-coordinator/src/real/mod.rs b/node/core/dispute-coordinator/src/real/mod.rs index 63d2d95c7048..05b1a6343ddc 100644 --- a/node/core/dispute-coordinator/src/real/mod.rs +++ b/node/core/dispute-coordinator/src/real/mod.rs @@ -56,6 +56,7 @@ use kvdb::KeyValueDB; use parity_scale_codec::{Decode, Encode, Error as CodecError}; use sc_keystore::LocalKeystore; +use crate::metrics::Metrics; use backend::{Backend, OverlayedBackend}; use db::v1::{DbBackend, RecentDisputes}; use metrics::Metrics; @@ -882,7 +883,6 @@ async fn issue_local_statement( let voted_indices: HashSet<_> = voted_indices.into_iter().collect(); let controlled_indices = find_controlled_validator_indices(&state.keystore, &validators[..]); - for index in controlled_indices { if voted_indices.contains(&index) { continue diff --git a/node/malus/Cargo.toml b/node/malus/Cargo.toml index 531eda7d142b..ef45fc4517f6 100644 --- a/node/malus/Cargo.toml +++ b/node/malus/Cargo.toml @@ -36,3 +36,8 @@ tracing = "0.1.26" [features] default = [] # we do not enable disputes by default to avoid feature leak disputes = ["polkadot-cli/disputes"] + +[dev-dependencies] +polkadot-node-subsystem-test-helpers = { path = "../subsystem-test-helpers" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +futures = { version = "0.3.17", features = ["thread-pool"] } diff --git a/node/malus/src/interceptor.rs b/node/malus/src/interceptor.rs index f351365c8e1f..abd4c6cfe76d 100644 --- a/node/malus/src/interceptor.rs +++ b/node/malus/src/interceptor.rs @@ -24,6 +24,9 @@ use polkadot_node_subsystem::*; pub use polkadot_node_subsystem::{messages::AllMessages, overseer, FromOverseer}; use std::{future::Future, pin::Pin}; +#[cfg(test)] +mod tests; + /// Filter incoming and outgoing messages. pub trait MessageInterceptor: Send + Sync + Clone + 'static where @@ -53,13 +56,13 @@ where /// A sender with the outgoing messages filtered. #[derive(Clone)] -pub struct FilteredSender { +pub struct InterceptedSender { inner: Sender, message_filter: Fil, } #[async_trait::async_trait] -impl overseer::SubsystemSender for FilteredSender +impl overseer::SubsystemSender for InterceptedSender where Sender: overseer::SubsystemSender + overseer::SubsystemSender<>::Message>, @@ -89,7 +92,7 @@ where } /// A subsystem context, that filters the outgoing messages. -pub struct FilteredContext +pub struct InterceptedContext where Context: overseer::SubsystemContext + SubsystemContext, Fil: MessageInterceptor<::Sender>, @@ -99,10 +102,10 @@ where { inner: Context, message_filter: Fil, - sender: FilteredSender<::Sender, Fil>, + sender: InterceptedSender<::Sender, Fil>, } -impl FilteredContext +impl InterceptedContext where Context: overseer::SubsystemContext + SubsystemContext, Fil: MessageInterceptor< @@ -114,7 +117,7 @@ where >, { pub fn new(mut inner: Context, message_filter: Fil) -> Self { - let sender = FilteredSender::<::Sender, Fil> { + let sender = InterceptedSender::<::Sender, Fil> { inner: inner.sender().clone(), message_filter: message_filter.clone(), }; @@ -123,7 +126,7 @@ where } #[async_trait::async_trait] -impl overseer::SubsystemContext for FilteredContext +impl overseer::SubsystemContext for InterceptedContext where Context: overseer::SubsystemContext + SubsystemContext, Fil: MessageInterceptor< @@ -137,7 +140,7 @@ where >, { type Message = ::Message; - type Sender = FilteredSender<::Sender, Fil>; + type Sender = InterceptedSender<::Sender, Fil>; type Error = ::Error; type AllMessages = ::AllMessages; type Signal = ::Signal; @@ -187,33 +190,33 @@ where } /// A subsystem to which incoming and outgoing filters are applied. -pub struct FilteredSubsystem { - subsystem: Sub, - message_filter: Fil, +pub struct InterceptedSubsystem { + pub subsystem: Sub, + pub message_interceptor: Interceptor, } -impl FilteredSubsystem { - pub fn new(subsystem: Sub, message_filter: Fil) -> Self { - Self { subsystem, message_filter } +impl InterceptedSubsystem { + pub fn new(subsystem: Sub, message_interceptor: Interceptor) -> Self { + Self { subsystem, message_interceptor } } } -impl overseer::Subsystem for FilteredSubsystem +impl overseer::Subsystem for InterceptedSubsystem where Context: overseer::SubsystemContext + SubsystemContext + Sync + Send, - Sub: overseer::Subsystem, SubsystemError>, - FilteredContext: overseer::SubsystemContext + SubsystemContext, - Fil: MessageInterceptor< + Sub: overseer::Subsystem, SubsystemError>, + InterceptedContext: overseer::SubsystemContext + SubsystemContext, + Interceptor: MessageInterceptor< ::Sender, Message = ::Message, >, ::Sender: overseer::SubsystemSender< - ::Sender>>::Message, + ::Sender>>::Message, >, { fn start(self, ctx: Context) -> SpawnedSubsystem { - let ctx = FilteredContext::new(ctx, self.message_filter); - overseer::Subsystem::, SubsystemError>::start( + let ctx = InterceptedContext::new(ctx, self.message_interceptor); + overseer::Subsystem::, SubsystemError>::start( self.subsystem, ctx, ) diff --git a/node/malus/src/tests.rs b/node/malus/src/tests.rs new file mode 100644 index 000000000000..00c39dd7b2b5 --- /dev/null +++ b/node/malus/src/tests.rs @@ -0,0 +1,90 @@ +// Copyright 2021 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +use super::*; + +use polkadot_node_subsystem_test_helpers::*; + +use polkadot_node_subsystem::{ + messages::{AllMessages, AvailabilityStoreMessage}, + overseer::{gen::TimeoutExt, Subsystem}, + DummySubsystem, +}; + +#[derive(Clone, Debug)] +struct BlackHoleInterceptor; + +impl MessageInterceptor for BlackHoleInterceptor +where + Sender: overseer::SubsystemSender + + overseer::SubsystemSender + + Clone + + 'static, +{ + type Message = AvailabilityStoreMessage; + fn intercept_incoming( + &self, + _sender: &mut Sender, + msg: FromOverseer, + ) -> Option> { + match msg { + FromOverseer::Communication { msg: _msg } => None, + // to conclude the test cleanly + sig => Some(sig), + } + } +} + +async fn overseer_send>(overseer: &mut TestSubsystemContextHandle, msg: T) { + overseer.send(FromOverseer::Communication { msg }).await; +} + +#[test] +fn integrity_test() { + let pool = sp_core::testing::TaskExecutor::new(); + let (context, mut overseer) = make_subsystem_context(pool); + + let sub = DummySubsystem; + + let sub_intercepted = InterceptedSubsystem::new(sub, BlackHoleInterceptor); + + // Try to send a message we know is going to be filtered. + let test_fut = async move { + let (tx, rx) = futures::channel::oneshot::channel(); + overseer_send( + &mut overseer, + AvailabilityStoreMessage::QueryChunk(Default::default(), 0.into(), tx), + ) + .await; + let _ = rx.timeout(std::time::Duration::from_millis(100)).await.unwrap(); + overseer + }; + let subsystem = async move { + sub_intercepted.start(context).future.await.unwrap(); + }; + + futures::pin_mut!(test_fut); + futures::pin_mut!(subsystem); + + futures::executor::block_on(futures::future::join( + async move { + let mut overseer = test_fut.await; + overseer.send(FromOverseer::Signal(OverseerSignal::Conclude)).await; + }, + subsystem, + )) + .1; +} diff --git a/node/network/gossip-support/src/lib.rs b/node/network/gossip-support/src/lib.rs index 1cdfaf4f5d9e..52c6ffc165be 100644 --- a/node/network/gossip-support/src/lib.rs +++ b/node/network/gossip-support/src/lib.rs @@ -54,7 +54,6 @@ const BACKOFF_DURATION: Duration = Duration::from_secs(5); /// should be fine: /// /// https://github.com/paritytech/substrate/blob/fc49802f263529160635471c8a17888846035f5d/client/authority-discovery/src/lib.rs#L88 -/// const LOW_CONNECTIVITY_WARN_DELAY: Duration = Duration::from_secs(600); /// The Gossip Support subsystem. @@ -292,14 +291,19 @@ impl State { ); } - let authorities = determine_relevant_authorities(ctx, relay_parent).await?; - let our_index = ensure_i_am_an_authority(keystore, &authorities).await?; + let all_authorities = determine_relevant_authorities(ctx, relay_parent).await?; + let our_index = ensure_i_am_an_authority(keystore, &all_authorities).await?; + let other_authorities = { + let mut authorities = all_authorities.clone(); + authorities.swap_remove(our_index); + authorities + }; - self.issue_connection_request(ctx, authorities.clone()).await?; + self.issue_connection_request(ctx, other_authorities).await?; if is_new_session { self.last_session_index = Some(session_index); - update_gossip_topology(ctx, our_index, authorities, relay_parent).await?; + update_gossip_topology(ctx, our_index, all_authorities, relay_parent).await?; } } } diff --git a/node/network/gossip-support/src/tests.rs b/node/network/gossip-support/src/tests.rs index f858ae1bc9cf..1ca76728adb9 100644 --- a/node/network/gossip-support/src/tests.rs +++ b/node/network/gossip-support/src/tests.rs @@ -92,20 +92,27 @@ async fn overseer_recv(overseer: &mut VirtualOverseer) -> AllMessages { } fn authorities() -> Vec { + let mut authorities = other_authorities(); + authorities.push(Sr25519Keyring::Ferdie.public().into()); + authorities +} + +// Authorities other than ourselves: +fn other_authorities() -> Vec { vec![ Sr25519Keyring::Alice.public().into(), Sr25519Keyring::Bob.public().into(), Sr25519Keyring::Charlie.public().into(), - Sr25519Keyring::Ferdie.public().into(), Sr25519Keyring::Eve.public().into(), Sr25519Keyring::One.public().into(), + Sr25519Keyring::Two.public().into(), ] } fn neighbors() -> Vec { vec![ - Sr25519Keyring::One.public().into(), - Sr25519Keyring::Alice.public().into(), + Sr25519Keyring::Two.public().into(), + Sr25519Keyring::Charlie.public().into(), Sr25519Keyring::Eve.public().into(), ] } @@ -177,7 +184,7 @@ fn issues_a_connection_request_on_new_session() { peer_set, failed, }) => { - assert_eq!(validator_ids, authorities()); + assert_eq!(validator_ids, other_authorities()); assert_eq!(peer_set, PeerSet::Validation); failed.send(0).unwrap(); } @@ -245,7 +252,7 @@ fn issues_a_connection_request_on_new_session() { peer_set, failed, }) => { - assert_eq!(validator_ids, authorities()); + assert_eq!(validator_ids, other_authorities()); assert_eq!(peer_set, PeerSet::Validation); failed.send(0).unwrap(); } @@ -293,7 +300,7 @@ fn issues_a_connection_request_when_last_request_was_mostly_unresolved() { peer_set, failed, }) => { - assert_eq!(validator_ids, authorities()); + assert_eq!(validator_ids, other_authorities()); assert_eq!(peer_set, PeerSet::Validation); failed.send(2).unwrap(); } @@ -340,7 +347,7 @@ fn issues_a_connection_request_when_last_request_was_mostly_unresolved() { peer_set, failed, }) => { - assert_eq!(validator_ids, authorities()); + assert_eq!(validator_ids, other_authorities()); assert_eq!(peer_set, PeerSet::Validation); failed.send(1).unwrap(); } diff --git a/node/network/protocol/src/request_response/outgoing.rs b/node/network/protocol/src/request_response/outgoing.rs index 38e3c44c7dae..e76b7b0eaac2 100644 --- a/node/network/protocol/src/request_response/outgoing.rs +++ b/node/network/protocol/src/request_response/outgoing.rs @@ -82,11 +82,11 @@ pub type ResponseSender = oneshot::Sender, network::RequestFailur #[derive(Debug, Error)] pub enum RequestError { /// Response could not be decoded. - #[error("Response could not be decoded")] + #[error("Response could not be decoded: {0}")] InvalidResponse(#[source] DecodingError), /// Some error in substrate/libp2p happened. - #[error("Some network error occurred")] + #[error("{0}")] NetworkError(#[source] network::RequestFailure), /// Response got canceled by networking. diff --git a/node/overseer/src/lib.rs b/node/overseer/src/lib.rs index 57effe57681f..935cf6ebbef8 100644 --- a/node/overseer/src/lib.rs +++ b/node/overseer/src/lib.rs @@ -94,7 +94,7 @@ pub use polkadot_node_subsystem_types::{ // TODO legacy, to be deleted, left for easier integration // TODO https://github.com/paritytech/polkadot/issues/3427 mod subsystems; -pub use self::subsystems::AllSubsystems; +pub use self::subsystems::{AllSubsystems, DummySubsystem}; mod metrics; use self::metrics::Metrics; diff --git a/node/service/src/chain_spec.rs b/node/service/src/chain_spec.rs index 7fbb0283f7cb..3aa03350113b 100644 --- a/node/service/src/chain_spec.rs +++ b/node/service/src/chain_spec.rs @@ -186,7 +186,6 @@ fn default_parachains_host_configuration( ump_service_total_weight: 4 * 1_000_000_000, max_upward_message_size: 1024 * 1024, max_upward_message_num_per_candidate: 5, - _hrmp_open_request_ttl: 5, hrmp_sender_deposit: 0, hrmp_recipient_deposit: 0, hrmp_channel_max_capacity: 8, diff --git a/node/subsystem-test-helpers/src/lib.rs b/node/subsystem-test-helpers/src/lib.rs index fe2b19144d5e..80dae08825b0 100644 --- a/node/subsystem-test-helpers/src/lib.rs +++ b/node/subsystem-test-helpers/src/lib.rs @@ -150,22 +150,25 @@ pub fn sender_receiver() -> (TestSubsystemSender, mpsc::UnboundedReceiver for TestSubsystemSender { - async fn send_message(&mut self, msg: AllMessages) { - self.tx.send(msg).await.expect("test overseer no longer live"); +impl overseer::SubsystemSender for TestSubsystemSender +where + T: Into + Send + 'static, +{ + async fn send_message(&mut self, msg: T) { + self.tx.send(msg.into()).await.expect("test overseer no longer live"); } - async fn send_messages(&mut self, msgs: T) + async fn send_messages(&mut self, msgs: X) where - T: IntoIterator + Send, - T::IntoIter: Send, + X: IntoIterator + Send, + X::IntoIter: Send, { - let mut iter = stream::iter(msgs.into_iter().map(Ok)); + let mut iter = stream::iter(msgs.into_iter().map(|msg| Ok(msg.into()))); self.tx.send_all(&mut iter).await.expect("test overseer no longer live"); } - fn send_unbounded_message(&mut self, msg: AllMessages) { - self.tx.unbounded_send(msg).expect("test overseer no longer live"); + fn send_unbounded_message(&mut self, msg: T) { + self.tx.unbounded_send(msg.into()).expect("test overseer no longer live"); } } diff --git a/node/subsystem-util/src/runtime/mod.rs b/node/subsystem-util/src/runtime/mod.rs index e1ac19e0e8fc..f086d31c661c 100644 --- a/node/subsystem-util/src/runtime/mod.rs +++ b/node/subsystem-util/src/runtime/mod.rs @@ -199,7 +199,7 @@ impl RuntimeInfo { /// Build `ValidatorInfo` for the current session. /// /// - /// Returns: `None` if not a validator. + /// Returns: `None` if not a parachain validator. async fn get_validator_info(&self, session_info: &SessionInfo) -> Result { if let Some(our_index) = self.get_our_index(&session_info.validators).await { // Get our group index: diff --git a/node/subsystem/src/lib.rs b/node/subsystem/src/lib.rs index e7ae19bcb39e..f0918ab1dc02 100644 --- a/node/subsystem/src/lib.rs +++ b/node/subsystem/src/lib.rs @@ -24,7 +24,7 @@ pub use jaeger::*; pub use polkadot_node_jaeger as jaeger; -pub use polkadot_overseer::{self as overseer, ActiveLeavesUpdate, OverseerSignal}; +pub use polkadot_overseer::{self as overseer, ActiveLeavesUpdate, DummySubsystem, OverseerSignal}; pub use polkadot_node_subsystem_types::{ errors::{self, *}, diff --git a/node/test/polkadot-simnet/common/src/lib.rs b/node/test/polkadot-simnet/common/src/lib.rs index 1d9d76708ae1..c2d7ac3c67de 100644 --- a/node/test/polkadot-simnet/common/src/lib.rs +++ b/node/test/polkadot-simnet/common/src/lib.rs @@ -31,7 +31,7 @@ use sc_executor::NativeElseWasmExecutor; use sc_service::{TFullBackend, TFullClient}; use sp_runtime::{app_crypto::sp_core::H256, generic::Era, AccountId32}; use std::{error::Error, future::Future, str::FromStr}; -use support::{weights::Weight, StorageValue}; +use support::weights::Weight; use test_runner::{ build_runtime, client_parts, ChainInfo, ConfigOrChainSpec, Node, SignatureVerificationOverride, }; @@ -138,7 +138,7 @@ where let proposal_hash = { // note the call (pre-image?) of the call. node.submit_extrinsic( - DemocracyCall::note_preimage(call.into().encode()), + DemocracyCall::note_preimage { encoded_proposal: call.into().encode() }, Some(whales[0].clone()), ) .await?; @@ -161,15 +161,16 @@ where // submit external_propose call through council collective { - let external_propose = - DemocracyCall::external_propose_majority(proposal_hash.clone().into()); + let external_propose = DemocracyCall::external_propose_majority { + proposal_hash: proposal_hash.clone().into(), + }; let length = external_propose.using_encoded(|x| x.len()) as u32 + 1; let weight = Weight::MAX / 100_000_000; - let proposal = CouncilCollectiveCall::propose( - council_collective.len() as u32, - Box::new(external_propose.clone().into()), - length, - ); + let proposal = CouncilCollectiveCall::propose { + threshold: council_collective.len() as u32, + proposal: Box::new(external_propose.clone().into()), + length_bound: length, + }; node.submit_extrinsic(proposal.clone(), Some(council_collective[0].clone())) .await?; @@ -191,13 +192,18 @@ where // vote for member in &council_collective[1..] { - let call = CouncilCollectiveCall::vote(hash.clone(), index, true); + let call = CouncilCollectiveCall::vote { proposal: hash.clone(), index, approve: true }; node.submit_extrinsic(call, Some(member.clone())).await?; } node.seal_blocks(1).await; // close vote - let call = CouncilCollectiveCall::close(hash, index, weight, length); + let call = CouncilCollectiveCall::close { + proposal_hash: hash, + index, + proposal_weight_bound: weight, + length_bound: length, + }; node.submit_extrinsic(call, Some(council_collective[0].clone())).await?; node.seal_blocks(1).await; @@ -227,15 +233,18 @@ where // next technical collective must fast track the proposal. { - let fast_track = - DemocracyCall::fast_track(proposal_hash.into(), FastTrackVotingPeriod::get(), 0); + let fast_track = DemocracyCall::fast_track { + proposal_hash: proposal_hash.into(), + voting_period: FastTrackVotingPeriod::get(), + delay: 0, + }; let weight = Weight::MAX / 100_000_000; let length = fast_track.using_encoded(|x| x.len()) as u32 + 1; - let proposal = TechnicalCollectiveCall::propose( - technical_collective.len() as u32, - Box::new(fast_track.into()), - length, - ); + let proposal = TechnicalCollectiveCall::propose { + threshold: technical_collective.len() as u32, + proposal: Box::new(fast_track.into()), + length_bound: length, + }; node.submit_extrinsic(proposal, Some(technical_collective[0].clone())).await?; node.seal_blocks(1).await; @@ -259,13 +268,19 @@ where // vote for member in &technical_collective[1..] { - let call = TechnicalCollectiveCall::vote(hash.clone(), index, true); + let call = + TechnicalCollectiveCall::vote { proposal: hash.clone(), index, approve: true }; node.submit_extrinsic(call, Some(member.clone())).await?; } node.seal_blocks(1).await; // close vote - let call = TechnicalCollectiveCall::close(hash, index, weight, length); + let call = CouncilCollectiveCall::close { + proposal_hash: hash, + index, + proposal_weight_bound: weight, + length_bound: length, + }; node.submit_extrinsic(call, Some(technical_collective[0].clone())).await?; node.seal_blocks(1).await; @@ -309,14 +324,14 @@ where format!("democracy::Event::Started not found in events: {:#?}", node.events()) })?; - let call = DemocracyCall::vote( + let call = DemocracyCall::vote { ref_index, - AccountVote::Standard { + vote: AccountVote::Standard { vote: Vote { aye: true, conviction: Conviction::Locked1x }, // 10 DOTS balance: 10_000_000_000_000, }, - ); + }; for whale in whales { node.submit_extrinsic(call.clone(), Some(whale)).await?; } @@ -404,9 +419,12 @@ mod tests { node.seal_blocks(1).await; // submit extrinsics let alice = MultiSigner::from(Alice.public()).into_account(); - node.submit_extrinsic(system::Call::remark((b"hello world").to_vec()), Some(alice)) - .await - .unwrap(); + node.submit_extrinsic( + system::Call::remark { remark: (b"hello world").to_vec() }, + Some(alice), + ) + .await + .unwrap(); // look ma, I can read state. let _events = node.with_state(|| system::Pallet::::events()); diff --git a/node/test/polkadot-simnet/test/src/main.rs b/node/test/polkadot-simnet/test/src/main.rs index 240167aa54fe..e637c72ba076 100644 --- a/node/test/polkadot-simnet/test/src/main.rs +++ b/node/test/polkadot-simnet/test/src/main.rs @@ -35,7 +35,7 @@ fn main() -> Result<(), Box> { .ok_or("Polkadot development wasm not available")? .to_vec(); // upgrade runtime. - dispatch_with_root(system::Call::set_code(wasm_binary), &node).await?; + dispatch_with_root(system::Call::set_code { code: wasm_binary }, &node).await?; // assert that the runtime has been updated by looking at events let events = node @@ -74,8 +74,11 @@ fn main() -> Result<(), Box> { ); // post upgrade tests, a simple balance transfer - node.submit_extrinsic(balances::Call::transfer(dest.into(), balance), Some(from)) - .await?; + node.submit_extrinsic( + balances::Call::transfer { dest: dest.into(), value: balance }, + Some(from), + ) + .await?; node.seal_blocks(1).await; let events = node diff --git a/node/test/service/src/lib.rs b/node/test/service/src/lib.rs index 447c8afd5d4f..d52b9ecc3284 100644 --- a/node/test/service/src/lib.rs +++ b/node/test/service/src/lib.rs @@ -286,16 +286,16 @@ impl PolkadotTestNode { validation_code: impl Into, genesis_head: impl Into, ) -> Result<(), RpcTransactionError> { - let call = ParasSudoWrapperCall::sudo_schedule_para_initialize( + let call = ParasSudoWrapperCall::sudo_schedule_para_initialize { id, - ParaGenesisArgs { + genesis: ParaGenesisArgs { genesis_head: genesis_head.into(), validation_code: validation_code.into(), parachain: true, }, - ); + }; - self.send_extrinsic(SudoCall::sudo(Box::new(call.into())), Sr25519Keyring::Alice) + self.send_extrinsic(SudoCall::sudo { call: Box::new(call.into()) }, Sr25519Keyring::Alice) .await .map(drop) } @@ -377,10 +377,10 @@ pub fn construct_transfer_extrinsic( dest: sp_keyring::AccountKeyring, value: Balance, ) -> UncheckedExtrinsic { - let function = polkadot_test_runtime::Call::Balances(pallet_balances::Call::transfer( - MultiSigner::from(dest.public()).into_account().into(), + let function = polkadot_test_runtime::Call::Balances(pallet_balances::Call::transfer { + dest: MultiSigner::from(dest.public()).into_account().into(), value, - )); + }); construct_extrinsic(client, function, origin, 0) } diff --git a/node/test/service/tests/call-function.rs b/node/test/service/tests/call-function.rs index 794a9e5c43c3..9a6ea4950ff9 100644 --- a/node/test/service/tests/call-function.rs +++ b/node/test/service/tests/call-function.rs @@ -22,10 +22,10 @@ async fn call_function_actually_work() { let alice = run_validator_node(tokio::runtime::Handle::current(), Alice, || {}, Vec::new(), None); - let function = polkadot_test_runtime::Call::Balances(pallet_balances::Call::transfer( - Default::default(), - 1, - )); + let function = polkadot_test_runtime::Call::Balances(pallet_balances::Call::transfer { + dest: Default::default(), + value: 1, + }); let output = alice.send_extrinsic(function, Bob).await.unwrap(); let res = output.result.expect("return value expected"); diff --git a/parachain/Cargo.toml b/parachain/Cargo.toml index e4ff85cc20ec..97ce76d38f0f 100644 --- a/parachain/Cargo.toml +++ b/parachain/Cargo.toml @@ -11,6 +11,7 @@ edition = "2018" # various unnecessary Substrate-specific endpoints. parity-scale-codec = { version = "2.0.0", default-features = false, features = [ "derive" ] } parity-util-mem = { version = "0.10.0", optional = true } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -26,6 +27,7 @@ default = ["std"] wasm-api = [] std = [ "parity-scale-codec/std", + "scale-info/std", "serde/std", "sp-std/std", "sp-runtime/std", diff --git a/parachain/src/primitives.rs b/parachain/src/primitives.rs index 900c75c6cd34..bda56bf59e8c 100644 --- a/parachain/src/primitives.rs +++ b/parachain/src/primitives.rs @@ -21,6 +21,7 @@ use sp_std::vec::Vec; use frame_support::weights::Weight; use parity_scale_codec::{CompactAs, Decode, Encode}; +use scale_info::TypeInfo; use sp_core::{RuntimeDebug, TypeId}; use sp_runtime::traits::Hash as _; @@ -40,7 +41,7 @@ pub use polkadot_core_primitives::BlockNumber as RelayChainBlockNumber; /// Parachain head data included in the chain. #[derive( - PartialEq, Eq, Clone, PartialOrd, Ord, Encode, Decode, RuntimeDebug, derive_more::From, + PartialEq, Eq, Clone, PartialOrd, Ord, Encode, Decode, RuntimeDebug, derive_more::From, TypeInfo, )] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Default, Hash, MallocSizeOf))] pub struct HeadData(#[cfg_attr(feature = "std", serde(with = "bytes"))] pub Vec); @@ -53,7 +54,9 @@ impl HeadData { } /// Parachain validation code. -#[derive(Default, PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, derive_more::From)] +#[derive( + Default, PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, derive_more::From, TypeInfo, +)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash, MallocSizeOf))] pub struct ValidationCode(#[cfg_attr(feature = "std", serde(with = "bytes"))] pub Vec); @@ -69,7 +72,7 @@ impl ValidationCode { /// This type is produced by [`ValidationCode::hash`]. /// /// This type makes it easy to enforce that a hash is a validation code hash on the type level. -#[derive(Clone, Copy, Encode, Decode, Default, Hash, Eq, PartialEq, PartialOrd, Ord)] +#[derive(Clone, Copy, Encode, Decode, Default, Hash, Eq, PartialEq, PartialOrd, Ord, TypeInfo)] #[cfg_attr(feature = "std", derive(MallocSizeOf))] pub struct ValidationCodeHash(Hash); @@ -112,7 +115,7 @@ impl sp_std::fmt::LowerHex for ValidationCodeHash { /// Parachain block data. /// /// Contains everything required to validate para-block, may contain block and witness data. -#[derive(PartialEq, Eq, Clone, Encode, Decode, derive_more::From)] +#[derive(PartialEq, Eq, Clone, Encode, Decode, derive_more::From, TypeInfo)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug, MallocSizeOf))] pub struct BlockData(#[cfg_attr(feature = "std", serde(with = "bytes"))] pub Vec); @@ -130,6 +133,7 @@ pub struct BlockData(#[cfg_attr(feature = "std", serde(with = "bytes"))] pub Vec PartialEq, PartialOrd, RuntimeDebug, + TypeInfo, )] #[cfg_attr( feature = "std", @@ -227,7 +231,9 @@ impl sp_std::ops::Sub for Id { } } -#[derive(Clone, Copy, Default, Encode, Decode, Eq, PartialEq, Ord, PartialOrd, RuntimeDebug)] +#[derive( + Clone, Copy, Default, Encode, Decode, Eq, PartialEq, Ord, PartialOrd, RuntimeDebug, TypeInfo, +)] pub struct Sibling(pub Id); impl From for Sibling { @@ -330,7 +336,7 @@ impl AccountIdConversion for Id { /// is allowed between two participants in one direction, i.e. there cannot be 2 different channels /// identified by `(A, B)`. A channel with the same para id in sender and recipient is invalid. That /// is, however, not enforced. -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Encode, Decode, RuntimeDebug)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Encode, Decode, RuntimeDebug, TypeInfo)] #[cfg_attr(feature = "std", derive(Hash))] pub struct HrmpChannelId { /// The para that acts as the sender in this channel. @@ -370,7 +376,7 @@ impl DmpMessageHandler for () { } /// The aggregate XCMP message format. -#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode)] +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)] pub enum XcmpMessageFormat { /// Encoded `VersionedXcm` messages, all concatenated. ConcatenatedVersionedXcm, diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml index 9b106e864cf7..4b2065d4cb6b 100644 --- a/primitives/Cargo.toml +++ b/primitives/Cargo.toml @@ -6,6 +6,7 @@ edition = "2018" [dependencies] serde = { version = "1.0.130", optional = true, features = ["derive"] } +scale-info = { version = "1.0", default-features = false, features = ["bit-vec", "derive"] } parity-scale-codec = { version = "2.0.0", default-features = false, features = ["bit-vec", "derive"] } primitives = { package = "sp-core", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } inherents = { package = "sp-inherents", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -34,6 +35,7 @@ default = ["std"] std = [ "application-crypto/std", "parity-scale-codec/std", + "scale-info/std", "primitives/std", "inherents/std", "trie/std", diff --git a/primitives/src/v0.rs b/primitives/src/v0.rs index 1cbeb916d482..7e15a0b87308 100644 --- a/primitives/src/v0.rs +++ b/primitives/src/v0.rs @@ -23,6 +23,7 @@ use bitvec::vec::BitVec; use parity_scale_codec::{Decode, Encode}; #[cfg(feature = "std")] use parity_util_mem::{MallocSizeOf, MallocSizeOfOps}; +use scale_info::TypeInfo; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; @@ -106,7 +107,7 @@ impl MallocSizeOf for ValidatorId { } /// Index of the validator is used as a lightweight replacement of the `ValidatorId` when appropriate. -#[derive(Eq, Ord, PartialEq, PartialOrd, Copy, Clone, Encode, Decode)] +#[derive(Eq, Ord, PartialEq, PartialOrd, Copy, Clone, Encode, Decode, TypeInfo)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug, Hash, MallocSizeOf))] pub struct ValidatorIndex(pub u32); @@ -139,7 +140,7 @@ impl MallocSizeOf for ValidatorSignature { } /// Retriability for a given active para. -#[derive(Clone, Eq, PartialEq, Encode, Decode)] +#[derive(Clone, Eq, PartialEq, Encode, Decode, TypeInfo)] #[cfg_attr(feature = "std", derive(Debug))] pub enum Retriable { /// Ineligible for retry. This means it's either a parachain that is always scheduled anyway or @@ -205,7 +206,7 @@ impl SwapAux for () { } /// Identifier for a chain, either one of a number of parachains or the relay chain. -#[derive(Copy, Clone, PartialEq, Encode, Decode)] +#[derive(Copy, Clone, PartialEq, Encode, Decode, TypeInfo)] #[cfg_attr(feature = "std", derive(Debug))] pub enum Chain { /// The relay chain. @@ -215,7 +216,7 @@ pub enum Chain { } /// The duty roster specifying what jobs each validator must do. -#[derive(Clone, PartialEq, Encode, Decode)] +#[derive(Clone, PartialEq, Encode, Decode, TypeInfo)] #[cfg_attr(feature = "std", derive(Default, Debug))] pub struct DutyRoster { /// Lookup from validator index to chain on which that validator has a duty to validate. @@ -226,7 +227,7 @@ pub struct DutyRoster { /// to fully validate the candidate. /// /// These are global parameters that apply to all parachain candidates in a block. -#[derive(PartialEq, Eq, Clone, Encode, Decode)] +#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo)] #[cfg_attr(feature = "std", derive(Debug, Default))] pub struct GlobalValidationData { /// The maximum code size permitted, in bytes. @@ -239,7 +240,7 @@ pub struct GlobalValidationData { /// Extra data that is needed along with the other fields in a `CandidateReceipt` /// to fully validate the candidate. These fields are parachain-specific. -#[derive(PartialEq, Eq, Clone, Encode, Decode)] +#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo)] #[cfg_attr(feature = "std", derive(Debug, Default))] pub struct LocalValidationData { /// The parent head-data. @@ -261,7 +262,7 @@ pub struct LocalValidationData { } /// Commitments made in a `CandidateReceipt`. Many of these are outputs of validation. -#[derive(PartialEq, Eq, Clone, Encode, Decode)] +#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo)] #[cfg_attr(feature = "std", derive(Debug, Default))] pub struct CandidateCommitments { /// Fees paid from the chain to the relay chain validators. @@ -310,7 +311,7 @@ fn check_collator_signature>( } /// All data pertaining to the execution of a parachain candidate. -#[derive(PartialEq, Eq, Clone, Encode, Decode)] +#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo)] #[cfg_attr(feature = "std", derive(Debug, Default))] pub struct CandidateReceipt { /// The ID of the parachain this is a candidate for. @@ -395,7 +396,7 @@ impl Ord for CandidateReceipt { /// All the data which is omitted in an `AbridgedCandidateReceipt`, but that /// is necessary for validation of the parachain candidate. -#[derive(PartialEq, Eq, Clone, Encode, Decode)] +#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo)] #[cfg_attr(feature = "std", derive(Debug, Default))] pub struct OmittedValidationData { /// The global validation schedule. @@ -409,7 +410,7 @@ pub struct OmittedValidationData { /// Much info in a candidate-receipt is duplicated from the relay-chain state. /// When submitting to the relay-chain, this data should be omitted as it can /// be re-generated from relay-chain state. -#[derive(PartialEq, Eq, Clone, Encode, Decode)] +#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo)] #[cfg_attr(feature = "std", derive(Debug, Default))] pub struct AbridgedCandidateReceipt { /// The ID of the parachain this is a candidate for. @@ -544,7 +545,7 @@ impl Ord for AbridgedCandidateReceipt { } /// A unique descriptor of the candidate receipt, in a lightweight format. -#[derive(PartialEq, Eq, Clone, Encode, Decode)] +#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo)] #[cfg_attr(feature = "std", derive(Debug, Default))] pub struct CandidateDescriptor { /// The ID of the para this is a candidate for. @@ -564,7 +565,7 @@ pub struct CandidateDescriptor { } /// A collation sent by a collator. -#[derive(PartialEq, Eq, Clone, Encode, Decode)] +#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo)] #[cfg_attr(feature = "std", derive(Debug, Default))] pub struct CollationInfo { /// The ID of the parachain this is a candidate for. @@ -619,7 +620,7 @@ impl CollationInfo { /// A full collation. #[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Debug, Encode, Decode))] +#[cfg_attr(feature = "std", derive(Debug, Encode, Decode, TypeInfo))] pub struct Collation { /// Candidate receipt itself. pub info: CollationInfo, @@ -629,7 +630,7 @@ pub struct Collation { /// A Proof-of-Validation block. #[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Debug, Encode, Decode))] +#[cfg_attr(feature = "std", derive(Debug, Encode, Decode, TypeInfo))] pub struct PoVBlock { /// Block data. pub block_data: BlockData, @@ -645,7 +646,7 @@ impl PoVBlock { /// The data that is kept available about a particular parachain block. #[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Debug, Encode, Decode))] +#[cfg_attr(feature = "std", derive(Debug, Encode, Decode, TypeInfo))] pub struct AvailableData { /// The PoV block. pub pov_block: PoVBlock, @@ -677,7 +678,7 @@ impl CompactStatement { } // Inner helper for codec on `CompactStatement`. -#[derive(Encode, Decode)] +#[derive(Encode, Decode, TypeInfo)] enum CompactStatementInner { #[codec(index = 1)] Seconded(CandidateHash), @@ -733,7 +734,7 @@ impl CompactStatement { /// An either implicit or explicit attestation to the validity of a parachain /// candidate. -#[derive(Clone, Eq, PartialEq, Decode, Encode, RuntimeDebug)] +#[derive(Clone, Eq, PartialEq, Decode, Encode, RuntimeDebug, TypeInfo)] pub enum ValidityAttestation { /// Implicit validity attestation by issuing. /// This corresponds to issuance of a `Candidate` statement. @@ -804,7 +805,7 @@ impl AttestedCandidate { } /// A fee schedule for messages. This is a linear function in the number of bytes of a message. -#[derive(PartialEq, Eq, PartialOrd, Hash, Default, Clone, Copy, Encode, Decode)] +#[derive(PartialEq, Eq, PartialOrd, Hash, Default, Clone, Copy, Encode, Decode, TypeInfo)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] pub struct FeeSchedule { /// The base fee charged for all messages. diff --git a/primitives/src/v1/mod.rs b/primitives/src/v1/mod.rs index dec17ca915a7..e32fb68f79db 100644 --- a/primitives/src/v1/mod.rs +++ b/primitives/src/v1/mod.rs @@ -18,6 +18,7 @@ use bitvec::vec::BitVec; use parity_scale_codec::{Decode, Encode}; +use scale_info::TypeInfo; use sp_std::{collections::btree_map::BTreeMap, prelude::*}; use application_crypto::KeyTypeId; @@ -319,7 +320,7 @@ fn check_collator_signature>( } /// A unique descriptor of the candidate receipt. -#[derive(PartialEq, Eq, Clone, Encode, Decode)] +#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo)] #[cfg_attr(feature = "std", derive(Debug, Default, Hash, MallocSizeOf))] pub struct CandidateDescriptor { /// The ID of the para this is a candidate for. @@ -361,7 +362,7 @@ impl> CandidateDescriptor { } /// A candidate-receipt. -#[derive(PartialEq, Eq, Clone, Encode, Decode)] +#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo)] #[cfg_attr(feature = "std", derive(Debug, Default, MallocSizeOf))] pub struct CandidateReceipt { /// The descriptor of the candidate. @@ -386,7 +387,7 @@ impl CandidateReceipt { } /// All data pertaining to the execution of a para candidate. -#[derive(PartialEq, Eq, Clone, Encode, Decode)] +#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo)] #[cfg_attr(feature = "std", derive(Debug, Default))] pub struct FullCandidateReceipt { /// The inner candidate receipt. @@ -399,7 +400,7 @@ pub struct FullCandidateReceipt { } /// A candidate-receipt with commitments directly included. -#[derive(PartialEq, Eq, Clone, Encode, Decode)] +#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo)] #[cfg_attr(feature = "std", derive(Debug, Default, Hash, MallocSizeOf))] pub struct CommittedCandidateReceipt { /// The descriptor of the candidate. @@ -480,7 +481,7 @@ impl Ord for CommittedCandidateReceipt { /// /// The `PersistedValidationData` should be relatively lightweight primarily because it is constructed /// during inclusion for each candidate and therefore lies on the critical path of inclusion. -#[derive(PartialEq, Eq, Clone, Encode, Decode)] +#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo)] #[cfg_attr(feature = "std", derive(Debug, Default, MallocSizeOf))] pub struct PersistedValidationData { /// The parent head-data. @@ -501,7 +502,7 @@ impl PersistedValidationData { } /// Commitments made in a `CandidateReceipt`. Many of these are outputs of validation. -#[derive(PartialEq, Eq, Clone, Encode, Decode)] +#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo)] #[cfg_attr(feature = "std", derive(Debug, Default, Hash, MallocSizeOf))] pub struct CandidateCommitments { /// Messages destined to be interpreted by the Relay chain itself. @@ -526,7 +527,7 @@ impl CandidateCommitments { } /// A bitfield concerning availability of backed candidates. -#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)] +#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo)] pub struct AvailabilityBitfield(pub BitVec); impl From> for AvailabilityBitfield { @@ -549,7 +550,7 @@ pub type SignedAvailabilityBitfields = Vec; pub type UncheckedSignedAvailabilityBitfields = Vec; /// A backed (or backable, depending on context) candidate. -#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] #[cfg_attr(feature = "std", derive(Default))] pub struct BackedCandidate { /// The candidate referred to. @@ -637,7 +638,7 @@ pub fn check_candidate_backing + Clone + Encode>( } /// The unique (during session) index of a core. -#[derive(Encode, Decode, Default, PartialOrd, Ord, Eq, PartialEq, Clone, Copy)] +#[derive(Encode, Decode, Default, PartialOrd, Ord, Eq, PartialEq, Clone, Copy, TypeInfo)] #[cfg_attr(feature = "std", derive(Debug, Hash, MallocSizeOf))] pub struct CoreIndex(pub u32); @@ -648,7 +649,7 @@ impl From for CoreIndex { } /// The unique (during session) index of a validator group. -#[derive(Encode, Decode, Default, Clone, Copy, Debug, PartialEq, Eq)] +#[derive(Encode, Decode, Default, Clone, Copy, Debug, PartialEq, Eq, TypeInfo)] #[cfg_attr(feature = "std", derive(Hash, MallocSizeOf))] pub struct GroupIndex(pub u32); @@ -659,12 +660,12 @@ impl From for GroupIndex { } /// A claim on authoring the next block for a given parathread. -#[derive(Clone, Encode, Decode, Default)] +#[derive(Clone, Encode, Decode, Default, TypeInfo)] #[cfg_attr(feature = "std", derive(PartialEq, Debug))] pub struct ParathreadClaim(pub Id, pub CollatorId); /// An entry tracking a claim to ensure it does not pass the maximum number of retries. -#[derive(Clone, Encode, Decode, Default)] +#[derive(Clone, Encode, Decode, Default, TypeInfo)] #[cfg_attr(feature = "std", derive(PartialEq, Debug))] pub struct ParathreadEntry { /// The claim. @@ -674,7 +675,7 @@ pub struct ParathreadEntry { } /// What is occupying a specific availability core. -#[derive(Clone, Encode, Decode)] +#[derive(Clone, Encode, Decode, TypeInfo)] #[cfg_attr(feature = "std", derive(PartialEq, Debug))] pub enum CoreOccupied { /// A parathread. @@ -684,7 +685,7 @@ pub enum CoreOccupied { } /// A helper data-type for tracking validator-group rotations. -#[derive(Clone, Encode, Decode)] +#[derive(Clone, Encode, Decode, TypeInfo)] #[cfg_attr(feature = "std", derive(PartialEq, Debug, MallocSizeOf))] pub struct GroupRotationInfo { /// The block number where the session started. @@ -772,7 +773,7 @@ impl GroupRotationInfo { } /// Information about a core which is currently occupied. -#[derive(Clone, Encode, Decode)] +#[derive(Clone, Encode, Decode, TypeInfo)] #[cfg_attr(feature = "std", derive(Debug, PartialEq, MallocSizeOf))] pub struct OccupiedCore { // NOTE: this has no ParaId as it can be deduced from the candidate descriptor. @@ -808,7 +809,7 @@ impl OccupiedCore { } /// Information about a core which is currently occupied. -#[derive(Clone, Encode, Decode)] +#[derive(Clone, Encode, Decode, TypeInfo)] #[cfg_attr(feature = "std", derive(Debug, PartialEq, Default, MallocSizeOf))] pub struct ScheduledCore { /// The ID of a para scheduled. @@ -818,7 +819,7 @@ pub struct ScheduledCore { } /// The state of a particular availability core. -#[derive(Clone, Encode, Decode)] +#[derive(Clone, Encode, Decode, TypeInfo)] #[cfg_attr(feature = "std", derive(Debug, PartialEq, MallocSizeOf))] pub enum CoreState { /// The core is currently occupied. @@ -854,7 +855,7 @@ impl CoreState { } /// An assumption being made about the state of an occupied core. -#[derive(Clone, Copy, Encode, Decode)] +#[derive(Clone, Copy, Encode, Decode, TypeInfo)] #[cfg_attr(feature = "std", derive(PartialEq, Eq, Hash, Debug))] pub enum OccupiedCoreAssumption { /// The candidate occupying the core was made available and included to free the core. @@ -869,7 +870,7 @@ pub enum OccupiedCoreAssumption { } /// An even concerning a candidate. -#[derive(Clone, Encode, Decode)] +#[derive(Clone, Encode, Decode, TypeInfo)] #[cfg_attr(feature = "std", derive(PartialEq, Debug, MallocSizeOf))] pub enum CandidateEvent { /// This candidate receipt was backed in the most recent block. @@ -888,15 +889,35 @@ pub enum CandidateEvent { } /// Information about validator sets of a session. -#[derive(Clone, Encode, Decode, RuntimeDebug)] +#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] #[cfg_attr(feature = "std", derive(PartialEq, Default, MallocSizeOf))] pub struct SessionInfo { /// Validators in canonical ordering. + /// + /// NOTE: There might be more authorities in the current session, than `validators` participating + /// in parachain consensus. See + /// [`max_validators`](https://github.com/paritytech/polkadot/blob/a52dca2be7840b23c19c153cf7e110b1e3e475f8/runtime/parachains/src/configuration.rs#L148). + /// + /// `SessionInfo::validators` will be limited to to `max_validators` when set. pub validators: Vec, /// Validators' authority discovery keys for the session in canonical ordering. + /// + /// NOTE: The first `validators.len()` entries will match the corresponding validators in + /// `validators`, afterwards any remaining authorities can be found. This is any authorities not + /// participating in parachain consensus - see + /// [`max_validators`](https://github.com/paritytech/polkadot/blob/a52dca2be7840b23c19c153cf7e110b1e3e475f8/runtime/parachains/src/configuration.rs#L148) #[cfg_attr(feature = "std", ignore_malloc_size_of = "outside type")] pub discovery_keys: Vec, /// The assignment keys for validators. + /// + /// NOTE: There might be more authorities in the current session, than validators participating + /// in parachain consensus. See + /// [`max_validators`](https://github.com/paritytech/polkadot/blob/a52dca2be7840b23c19c153cf7e110b1e3e475f8/runtime/parachains/src/configuration.rs#L148). + /// + /// Therefore: + /// ```ignore + /// assignment_keys.len() == validators.len() && validators.len() <= discovery_keys.len() + /// ``` pub assignment_keys: Vec, /// Validators in shuffled ordering - these are the validator groups as produced /// by the `Scheduler` module for the session and are typically referred to by @@ -1013,7 +1034,7 @@ impl From for u8 { /// Abridged version of `HostConfiguration` (from the `Configuration` parachains host runtime module) /// meant to be used by a parachain or PDK such as cumulus. -#[derive(Clone, Encode, Decode, RuntimeDebug)] +#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] #[cfg_attr(feature = "std", derive(PartialEq))] pub struct AbridgedHostConfiguration { /// The maximum validation code size, in bytes. @@ -1046,7 +1067,7 @@ pub struct AbridgedHostConfiguration { /// Abridged version of `HrmpChannel` (from the `Hrmp` parachains host runtime module) meant to be /// used by a parachain or PDK such as cumulus. -#[derive(Clone, Encode, Decode, RuntimeDebug)] +#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] #[cfg_attr(feature = "std", derive(PartialEq))] pub struct AbridgedHrmpChannel { /// The maximum number of messages that can be pending in the channel at once. @@ -1072,7 +1093,7 @@ pub struct AbridgedHrmpChannel { } /// A possible upgrade restriction that prevents a parachain from performing an upgrade. -#[derive(Encode, Decode, PartialEq, RuntimeDebug)] +#[derive(Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)] pub enum UpgradeRestriction { /// There is an upgrade restriction and there are no details about its specifics nor how long /// it could last. @@ -1085,7 +1106,7 @@ pub enum UpgradeRestriction { /// /// This data type appears in the last step of the upgrade process. After the parachain observes it /// and reacts to it the upgrade process concludes. -#[derive(Encode, Decode, PartialEq, RuntimeDebug)] +#[derive(Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)] pub enum UpgradeGoAhead { /// Abort the upgrade process. There is something wrong with the validation code previously /// submitted by the parachain. This variant can also be used to prevent upgrades by the governance @@ -1153,7 +1174,7 @@ impl From for runtime_primitives::DigestItem { /// A statement about a candidate, to be used within the dispute resolution process. /// /// Statements are either in favor of the candidate's validity or against it. -#[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug)] +#[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug, TypeInfo)] pub enum DisputeStatement { /// A valid statement, of the given kind. #[codec(index = 0)] @@ -1222,7 +1243,7 @@ impl DisputeStatement { } /// Different kinds of statements of validity on a candidate. -#[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug)] +#[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug, TypeInfo)] pub enum ValidDisputeStatementKind { /// An explicit statement issued as part of a dispute. #[codec(index = 0)] @@ -1239,7 +1260,7 @@ pub enum ValidDisputeStatementKind { } /// Different kinds of statements of invalidity on a candidate. -#[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug)] +#[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug, TypeInfo)] pub enum InvalidDisputeStatementKind { /// An explicit statement issued as part of a dispute. #[codec(index = 0)] @@ -1267,7 +1288,7 @@ impl ExplicitDisputeStatement { } /// A set of statements about a specific candidate. -#[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug)] +#[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug, TypeInfo)] pub struct DisputeStatementSet { /// The candidate referenced by this set. pub candidate_hash: CandidateHash, @@ -1281,7 +1302,7 @@ pub struct DisputeStatementSet { pub type MultiDisputeStatementSet = Vec; /// The entire state of a dispute. -#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq)] +#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, TypeInfo)] pub struct DisputeState { /// A bitfield indicating all validators for the candidate. pub validators_for: BitVec, // one bit per validator. @@ -1294,7 +1315,7 @@ pub struct DisputeState { } /// Parachains inherent-data passed into the runtime by a block author -#[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug)] +#[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug, TypeInfo)] pub struct InherentData { /// Signed bitfields by validators about availability. pub bitfields: UncheckedSignedAvailabilityBitfields, diff --git a/primitives/src/v1/signed.rs b/primitives/src/v1/signed.rs index 66908216ebb3..612cc1516895 100644 --- a/primitives/src/v1/signed.rs +++ b/primitives/src/v1/signed.rs @@ -15,6 +15,7 @@ // along with Polkadot. If not, see . use parity_scale_codec::{Decode, Encode}; +use scale_info::TypeInfo; #[cfg(feature = "std")] use application_crypto::AppKey; @@ -41,7 +42,7 @@ use crate::v0::{SigningContext, ValidatorId, ValidatorIndex, ValidatorSignature} pub struct Signed(UncheckedSigned); /// Unchecked signed data, can be converted to `Signed` by checking the signature. -#[derive(Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode)] +#[derive(Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, TypeInfo)] pub struct UncheckedSigned { /// The payload is part of the signed data. The rest is the signing context, /// which is known both at signing and at validation. diff --git a/roadmap/implementers-guide/src/runtime/session_info.md b/roadmap/implementers-guide/src/runtime/session_info.md index a37f61af08d7..5ee63ab5a903 100644 --- a/roadmap/implementers-guide/src/runtime/session_info.md +++ b/roadmap/implementers-guide/src/runtime/session_info.md @@ -8,27 +8,47 @@ Helper structs: ```rust struct SessionInfo { - // validators in canonical ordering. These are the public keys used for backing, - // dispute participation, and approvals. + /// Validators in canonical ordering. + /// + /// NOTE: There might be more authorities in the current session, than `validators` participating + /// in parachain consensus. See + /// [`max_validators`](https://github.com/paritytech/polkadot/blob/a52dca2be7840b23c19c153cf7e110b1e3e475f8/runtime/parachains/src/configuration.rs#L148). + /// + /// `SessionInfo::validators` will be limited to to `max_validators` when set. validators: Vec, - // validators' authority discovery keys for the session in canonical ordering. - discovery_keys: Vec, - // The assignment keys for validators. + /// Validators' authority discovery keys for the session in canonical ordering. + /// + /// NOTE: The first `validators.len()` entries will match the corresponding validators in + /// `validators`, afterwards any remaining authorities can be found. This is any authorities not + /// participating in parachain consensus - see + /// [`max_validators`](https://github.com/paritytech/polkadot/blob/a52dca2be7840b23c19c153cf7e110b1e3e475f8/runtime/parachains/src/configuration.rs#L148) + #[cfg_attr(feature = "std", ignore_malloc_size_of = "outside type")] + discovery_keys: Vec, + /// The assignment keys for validators. + /// + /// NOTE: There might be more authorities in the current session, than validators participating + /// in parachain consensus. See + /// [`max_validators`](https://github.com/paritytech/polkadot/blob/a52dca2be7840b23c19c153cf7e110b1e3e475f8/runtime/parachains/src/configuration.rs#L148). + /// + /// Therefore: + /// ```ignore + /// assignment_keys.len() == validators.len() && validators.len() <= discovery_keys.len() + /// ``` assignment_keys: Vec, - // validators in shuffled ordering - these are the validator groups as produced - // by the `Scheduler` module for the session and are typically referred to by - // `GroupIndex`. + /// Validators in shuffled ordering - these are the validator groups as produced + /// by the `Scheduler` module for the session and are typically referred to by + /// `GroupIndex`. validator_groups: Vec>, - // The number of availability cores used by the protocol during this session. + /// The number of availability cores used by the protocol during this session. n_cores: u32, - // the zeroth delay tranche width. + /// The zeroth delay tranche width. zeroth_delay_tranche_width: u32, - // The number of samples we do of relay_vrf_modulo. + /// The number of samples we do of `relay_vrf_modulo`. relay_vrf_modulo_samples: u32, - // The number of delay tranches in total. + /// The number of delay tranches in total. n_delay_tranches: u32, - // How many slots (BABE / SASSAFRAS) must pass before an assignment is considered a - // no-show. + /// How many slots (BABE / SASSAFRAS) must pass before an assignment is considered a + /// no-show. no_show_slots: u32, /// The number of validators needed to approve a block. needed_approvals: u32, diff --git a/runtime/common/Cargo.toml b/runtime/common/Cargo.toml index 9e3255969ecb..41e8d8fea71d 100644 --- a/runtime/common/Cargo.toml +++ b/runtime/common/Cargo.toml @@ -10,10 +10,12 @@ bitvec = { version = "0.20.1", default-features = false, features = ["alloc"] } parity-scale-codec = { version = "2.0.0", default-features = false, features = ["derive"] } log = { version = "0.4.13", default-features = false } rustc-hex = { version = "2.1.0", default-features = false } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0.130", default-features = false } serde_derive = { version = "1.0.117", optional = true } static_assertions = "1.1.0" +beefy-primitives = { git = "https://github.com/paritytech/grandpa-bridge-gadget", branch = "master", default-features = false } sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } inherents = { package = "sp-inherents", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-std = { package = "sp-std", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -63,6 +65,7 @@ no_std = [] std = [ "bitvec/std", "parity-scale-codec/std", + "scale-info/std", "log/std", "rustc-hex/std", "serde_derive", diff --git a/runtime/common/src/auctions.rs b/runtime/common/src/auctions.rs index caa609e1aff5..a3866fed2ba2 100644 --- a/runtime/common/src/auctions.rs +++ b/runtime/common/src/auctions.rs @@ -118,12 +118,6 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] - #[pallet::metadata( - T::AccountId = "AccountId", - T::BlockNumber = "BlockNumber", - LeasePeriodOf = "LeasePeriod", - BalanceOf = "Balance", - )] pub enum Event { /// An auction started. Provides its index and the block number where it will begin to /// close and the first lease period of the quadruplet that is auctioned. diff --git a/runtime/common/src/claims.rs b/runtime/common/src/claims.rs index f2be5a954b3c..a89bd0b4d03a 100644 --- a/runtime/common/src/claims.rs +++ b/runtime/common/src/claims.rs @@ -24,6 +24,7 @@ use frame_support::{ pub use pallet::*; use parity_scale_codec::{Decode, Encode}; use primitives::v1::ValidityError; +use scale_info::TypeInfo; #[cfg(feature = "std")] use serde::{self, Deserialize, Deserializer, Serialize, Serializer}; use sp_io::{crypto::secp256k1_ecdsa_recover, hashing::keccak_256}; @@ -71,7 +72,7 @@ impl WeightInfo for TestWeightInfo { } /// The kind of statement an account needs to make for a claim to be valid. -#[derive(Encode, Decode, Clone, Copy, Eq, PartialEq, RuntimeDebug)] +#[derive(Encode, Decode, Clone, Copy, Eq, PartialEq, RuntimeDebug, TypeInfo)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub enum StatementKind { /// Statement required to be made by non-SAFT holders. @@ -105,7 +106,7 @@ impl Default for StatementKind { /// An Ethereum address (i.e. 20 bytes, used to represent an Ethereum account). /// /// This gets serialized to the 0x-prefixed hex representation. -#[derive(Clone, Copy, PartialEq, Eq, Encode, Decode, Default, RuntimeDebug)] +#[derive(Clone, Copy, PartialEq, Eq, Encode, Decode, Default, RuntimeDebug, TypeInfo)] pub struct EthereumAddress([u8; 20]); #[cfg(feature = "std")] @@ -141,7 +142,7 @@ impl<'de> Deserialize<'de> for EthereumAddress { } } -#[derive(Encode, Decode, Clone)] +#[derive(Encode, Decode, Clone, TypeInfo)] pub struct EcdsaSignature(pub [u8; 65]); impl PartialEq for EcdsaSignature { @@ -180,7 +181,6 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] - #[pallet::metadata(T::AccountId = "AccountId", BalanceOf = "Balance")] pub enum Event { /// Someone claimed some DOTs. `[who, ethereum_address, amount]` Claimed(T::AccountId, EthereumAddress, BalanceOf), @@ -473,14 +473,14 @@ pub mod pallet { // // The weight of this logic is included in the `claim` dispatchable. // - Call::claim(account, ethereum_signature) => { + Call::claim { dest: account, ethereum_signature } => { let data = account.using_encoded(to_ascii_hex); (Self::eth_recover(ðereum_signature, &data, &[][..]), None) }, // // The weight of this logic is included in the `claim_attest` dispatchable. // - Call::claim_attest(account, ethereum_signature, statement) => { + Call::claim_attest { dest: account, ethereum_signature, statement } => { let data = account.using_encoded(to_ascii_hex); ( Self::eth_recover(ðereum_signature, &data, &statement), @@ -588,7 +588,8 @@ impl Pallet { /// Validate `attest` calls prior to execution. Needed to avoid a DoS attack since they are /// otherwise free to place on chain. -#[derive(Encode, Decode, Clone, Eq, PartialEq)] +#[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] +#[scale_info(skip_type_params(T))] pub struct PrevalidateAttests(sp_std::marker::PhantomData) where ::Call: IsSubType>; @@ -643,7 +644,7 @@ where _len: usize, ) -> TransactionValidity { if let Some(local_call) = call.is_sub_type() { - if let Call::attest(attested_statement) = local_call { + if let Call::attest { statement: attested_statement } = local_call { let signer = Preclaims::::get(who) .ok_or(InvalidTransaction::Custom(ValidityError::SignerHasNoClaim.into()))?; if let Some(s) = Signing::::get(signer) { @@ -1035,7 +1036,9 @@ mod tests { fn valid_attest_transactions_are_free() { new_test_ext().execute_with(|| { let p = PrevalidateAttests::::new(); - let c = Call::Claims(ClaimsCall::attest(StatementKind::Saft.to_text().to_vec())); + let c = Call::Claims(ClaimsCall::attest { + statement: StatementKind::Saft.to_text().to_vec(), + }); let di = c.get_dispatch_info(); assert_eq!(di.pays_fee, Pays::No); let r = p.validate(&42, &c, &di, 20); @@ -1047,11 +1050,15 @@ mod tests { fn invalid_attest_transactions_are_recognized() { new_test_ext().execute_with(|| { let p = PrevalidateAttests::::new(); - let c = Call::Claims(ClaimsCall::attest(StatementKind::Regular.to_text().to_vec())); + let c = Call::Claims(ClaimsCall::attest { + statement: StatementKind::Regular.to_text().to_vec(), + }); let di = c.get_dispatch_info(); let r = p.validate(&42, &c, &di, 20); assert!(r.is_err()); - let c = Call::Claims(ClaimsCall::attest(StatementKind::Saft.to_text().to_vec())); + let c = Call::Claims(ClaimsCall::attest { + statement: StatementKind::Saft.to_text().to_vec(), + }); let di = c.get_dispatch_info(); let r = p.validate(&69, &c, &di, 20); assert!(r.is_err()); @@ -1282,7 +1289,10 @@ mod tests { assert_eq!( >::validate_unsigned( source, - &ClaimsCall::claim(1, sig::(&alice(), &1u64.encode(), &[][..])) + &ClaimsCall::claim { + dest: 1, + ethereum_signature: sig::(&alice(), &1u64.encode(), &[][..]) + } ), Ok(ValidTransaction { priority: 100, @@ -1295,19 +1305,26 @@ mod tests { assert_eq!( >::validate_unsigned( source, - &ClaimsCall::claim(0, EcdsaSignature([0; 65])) + &ClaimsCall::claim { dest: 0, ethereum_signature: EcdsaSignature([0; 65]) } ), InvalidTransaction::Custom(ValidityError::InvalidEthereumSignature.into()).into(), ); assert_eq!( >::validate_unsigned( source, - &ClaimsCall::claim(1, sig::(&bob(), &1u64.encode(), &[][..])) + &ClaimsCall::claim { + dest: 1, + ethereum_signature: sig::(&bob(), &1u64.encode(), &[][..]) + } ), InvalidTransaction::Custom(ValidityError::SignerHasNoClaim.into()).into(), ); let s = sig::(&dave(), &1u64.encode(), StatementKind::Regular.to_text()); - let call = ClaimsCall::claim_attest(1, s, StatementKind::Regular.to_text().to_vec()); + let call = ClaimsCall::claim_attest { + dest: 1, + ethereum_signature: s, + statement: StatementKind::Regular.to_text().to_vec(), + }; assert_eq!( >::validate_unsigned(source, &call), Ok(ValidTransaction { @@ -1321,31 +1338,43 @@ mod tests { assert_eq!( >::validate_unsigned( source, - &ClaimsCall::claim_attest( - 1, - EcdsaSignature([0; 65]), - StatementKind::Regular.to_text().to_vec() - ) + &ClaimsCall::claim_attest { + dest: 1, + ethereum_signature: EcdsaSignature([0; 65]), + statement: StatementKind::Regular.to_text().to_vec() + } ), InvalidTransaction::Custom(ValidityError::InvalidEthereumSignature.into()).into(), ); let s = sig::(&bob(), &1u64.encode(), StatementKind::Regular.to_text()); - let call = ClaimsCall::claim_attest(1, s, StatementKind::Regular.to_text().to_vec()); + let call = ClaimsCall::claim_attest { + dest: 1, + ethereum_signature: s, + statement: StatementKind::Regular.to_text().to_vec(), + }; assert_eq!( >::validate_unsigned(source, &call), InvalidTransaction::Custom(ValidityError::SignerHasNoClaim.into()).into(), ); let s = sig::(&dave(), &1u64.encode(), StatementKind::Saft.to_text()); - let call = ClaimsCall::claim_attest(1, s, StatementKind::Regular.to_text().to_vec()); + let call = ClaimsCall::claim_attest { + dest: 1, + ethereum_signature: s, + statement: StatementKind::Regular.to_text().to_vec(), + }; assert_eq!( >::validate_unsigned(source, &call), InvalidTransaction::Custom(ValidityError::SignerHasNoClaim.into()).into(), ); let s = sig::(&dave(), &1u64.encode(), StatementKind::Saft.to_text()); - let call = ClaimsCall::claim_attest(1, s, StatementKind::Saft.to_text().to_vec()); + let call = ClaimsCall::claim_attest { + dest: 1, + ethereum_signature: s, + statement: StatementKind::Saft.to_text().to_vec(), + }; assert_eq!( >::validate_unsigned(source, &call), InvalidTransaction::Custom(ValidityError::InvalidStatement.into()).into(), @@ -1414,7 +1443,7 @@ mod benchmarking { super::Pallet::::mint_claim(RawOrigin::Root.into(), eth_address, VALUE.into(), vesting, None)?; assert_eq!(Claims::::get(eth_address), Some(VALUE.into())); let source = sp_runtime::transaction_validity::TransactionSource::External; - let call = Call::::claim(account.clone(), signature.clone()); + let call = Call::::claim { dest: account.clone(), ethereum_signature: signature.clone() }; }: { super::Pallet::::validate_unsigned(source, &call).map_err(|e| -> &'static str { e.into() })?; super::Pallet::::claim(RawOrigin::None.into(), account, signature)?; @@ -1459,7 +1488,7 @@ mod benchmarking { let signature = sig::(&secret_key, &account.encode(), statement.to_text()); super::Pallet::::mint_claim(RawOrigin::Root.into(), eth_address, VALUE.into(), vesting, Some(statement))?; assert_eq!(Claims::::get(eth_address), Some(VALUE.into())); - let call = Call::::claim_attest(account.clone(), signature.clone(), StatementKind::Regular.to_text().to_vec()); + let call = Call::::claim_attest { dest: account.clone(), ethereum_signature: signature.clone(), statement: StatementKind::Regular.to_text().to_vec() }; let source = sp_runtime::transaction_validity::TransactionSource::External; }: { super::Pallet::::validate_unsigned(source, &call).map_err(|e| -> &'static str { e.into() })?; @@ -1489,10 +1518,10 @@ mod benchmarking { Preclaims::::insert(&account, eth_address); assert_eq!(Claims::::get(eth_address), Some(VALUE.into())); - let call = super::Call::attest(StatementKind::Regular.to_text().to_vec()); + let call = super::Call::attest { statement: StatementKind::Regular.to_text().to_vec() }; // We have to copy the validate statement here because of trait issues... :( let validate = |who: &T::AccountId, call: &super::Call| -> DispatchResult { - if let Call::attest(attested_statement) = call { + if let Call::attest{ statement: attested_statement } = call { let signer = Preclaims::::get(who).ok_or("signer has no claim")?; if let Some(s) = Signing::::get(signer) { ensure!(&attested_statement[..] == s.to_text(), "invalid statement"); diff --git a/runtime/common/src/crowdloan.rs b/runtime/common/src/crowdloan.rs index e0dc0d4c8395..a97825d445c2 100644 --- a/runtime/common/src/crowdloan.rs +++ b/runtime/common/src/crowdloan.rs @@ -63,6 +63,7 @@ use frame_support::{ pub use pallet::*; use parity_scale_codec::{Decode, Encode}; use primitives::v1::Id as ParaId; +use scale_info::TypeInfo; use sp_runtime::{ traits::{ AccountIdConversion, CheckedAdd, Hash, IdentifyAccount, One, Saturating, Verify, Zero, @@ -124,7 +125,7 @@ impl WeightInfo for TestWeightInfo { } } -#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug)] +#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] pub enum LastContribution { Never, PreEnding(u32), @@ -133,7 +134,7 @@ pub enum LastContribution { /// Information on a funding effort for a pre-existing parachain. We assume that the parachain ID /// is known as it's used for the key of the storage item for which this is the value (`Funds`). -#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] #[codec(dumb_trait_bound)] pub struct FundInfo { /// The owning account who placed the deposit. @@ -242,7 +243,6 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] - #[pallet::metadata(T::AccountId = "AccountId", BalanceOf = "Balance")] pub enum Event { /// Create a new crowdloaning campaign. `[fund_index]` Created(ParaId), diff --git a/runtime/common/src/paras_registrar.rs b/runtime/common/src/paras_registrar.rs index 3c9e80993205..5f444bcffc0f 100644 --- a/runtime/common/src/paras_registrar.rs +++ b/runtime/common/src/paras_registrar.rs @@ -35,12 +35,13 @@ use sp_std::{prelude::*, result}; use crate::traits::{OnSwap, Registrar}; pub use pallet::*; use parity_scale_codec::{Decode, Encode}; +use scale_info::TypeInfo; use sp_runtime::{ traits::{CheckedSub, Saturating}, RuntimeDebug, }; -#[derive(Encode, Decode, Clone, PartialEq, Eq, Default, RuntimeDebug)] +#[derive(Encode, Decode, Clone, PartialEq, Eq, Default, RuntimeDebug, TypeInfo)] pub struct ParaInfo { /// The account that has placed a deposit for registering this para. pub(crate) manager: Account, @@ -124,7 +125,6 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] - #[pallet::metadata(T::AccountId = "AccountId")] pub enum Event { Registered(ParaId, T::AccountId), Deregistered(ParaId), diff --git a/runtime/common/src/purchase.rs b/runtime/common/src/purchase.rs index f2b2a7a299b8..5f86bf4226d5 100644 --- a/runtime/common/src/purchase.rs +++ b/runtime/common/src/purchase.rs @@ -23,6 +23,7 @@ use frame_support::{ use frame_system::pallet_prelude::*; pub use pallet::*; use parity_scale_codec::{Decode, Encode}; +use scale_info::TypeInfo; use sp_core::sr25519; use sp_runtime::{ traits::{CheckedAdd, Saturating, Verify, Zero}, @@ -34,7 +35,7 @@ type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; /// The kind of a statement an account needs to make for a claim to be valid. -#[derive(Encode, Decode, Clone, Copy, Eq, PartialEq, RuntimeDebug)] +#[derive(Encode, Decode, Clone, Copy, Eq, PartialEq, RuntimeDebug, TypeInfo)] pub enum AccountValidity { /// Account is not valid. Invalid, @@ -70,7 +71,7 @@ impl AccountValidity { } /// All information about an account regarding the purchase of DOTs. -#[derive(Encode, Decode, Default, Clone, Eq, PartialEq, RuntimeDebug)] +#[derive(Encode, Decode, Default, Clone, Eq, PartialEq, RuntimeDebug, TypeInfo)] pub struct AccountStatus { /// The current validity status of the user. Will denote if the user has passed KYC, /// how much they are able to purchase, and when their purchase process has completed. @@ -129,11 +130,6 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] - #[pallet::metadata( - T::AccountId = "AccountId", - T::BlockNumber = "BlockNumber", - BalanceOf = "Balance", - )] pub enum Event { /// A [new] account was created. AccountCreated(T::AccountId), @@ -1071,7 +1067,7 @@ mod tests { ); // Vesting lock is removed in whole on block 101 (100 blocks after block 1) System::set_block_number(100); - let vest_call = Call::Vesting(pallet_vesting::Call::::vest()); + let vest_call = Call::Vesting(pallet_vesting::Call::::vest {}); assert_ok!(vest_call.clone().dispatch(Origin::signed(alice()))); assert_ok!(vest_call.clone().dispatch(Origin::signed(bob()))); assert_eq!(::VestingSchedule::vesting_balance(&alice()), Some(45)); diff --git a/runtime/common/src/slots.rs b/runtime/common/src/slots.rs index 0dac47c71136..8fe4a77f187e 100644 --- a/runtime/common/src/slots.rs +++ b/runtime/common/src/slots.rs @@ -110,11 +110,6 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] - #[pallet::metadata( - T::AccountId = "AccountId", - LeasePeriodOf = "LeasePeriod", - BalanceOf = "Balance", - )] pub enum Event { /// A new `[lease_period]` is beginning. NewLeasePeriod(LeasePeriodOf), diff --git a/runtime/kusama/Cargo.toml b/runtime/kusama/Cargo.toml index 43284abb6425..26858f68d4ee 100644 --- a/runtime/kusama/Cargo.toml +++ b/runtime/kusama/Cargo.toml @@ -8,6 +8,7 @@ build = "build.rs" [dependencies] bitvec = { version = "0.20.1", default-features = false, features = ["alloc"] } parity-scale-codec = { version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } log = { version = "0.4.14", default-features = false } rustc-hex = { version = "2.1.0", default-features = false } serde = { version = "1.0.130", default-features = false } @@ -109,6 +110,7 @@ std = [ "primitives/std", "rustc-hex/std", "parity-scale-codec/std", + "scale-info/std", "inherents/std", "sp-core/std", "sp-api/std", diff --git a/runtime/kusama/src/lib.rs b/runtime/kusama/src/lib.rs index fdf93d69453e..fcb92a44f894 100644 --- a/runtime/kusama/src/lib.rs +++ b/runtime/kusama/src/lib.rs @@ -141,7 +141,7 @@ pub fn native_version() -> NativeVersion { pub struct BaseFilter; impl Contains for BaseFilter { fn contains(c: &Call) -> bool { - !matches!(c, Call::Registrar(paras_registrar::Call::swap(..))) + !matches!(c, Call::Registrar(paras_registrar::Call::swap { .. })) } } @@ -972,7 +972,17 @@ parameter_types! { /// The type used to represent the kinds of proxying allowed. #[derive( - Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, RuntimeDebug, MaxEncodedLen, + Copy, + Clone, + Eq, + PartialEq, + Ord, + PartialOrd, + Encode, + Decode, + RuntimeDebug, + MaxEncodedLen, + scale_info::TypeInfo, )] pub enum ProxyType { Any, @@ -997,9 +1007,9 @@ impl InstanceFilter for ProxyType { Call::System(..) | Call::Babe(..) | Call::Timestamp(..) | - Call::Indices(pallet_indices::Call::claim(..)) | - Call::Indices(pallet_indices::Call::free(..)) | - Call::Indices(pallet_indices::Call::freeze(..)) | + Call::Indices(pallet_indices::Call::claim {..}) | + Call::Indices(pallet_indices::Call::free {..}) | + Call::Indices(pallet_indices::Call::freeze {..}) | // Specifically omitting Indices `transfer`, `force_transfer` // Specifically omitting the entire Balances pallet Call::Authorship(..) | @@ -1019,24 +1029,24 @@ impl InstanceFilter for ProxyType { Call::Utility(..) | Call::Identity(..) | Call::Society(..) | - Call::Recovery(pallet_recovery::Call::as_recovered(..)) | - Call::Recovery(pallet_recovery::Call::vouch_recovery(..)) | - Call::Recovery(pallet_recovery::Call::claim_recovery(..)) | - Call::Recovery(pallet_recovery::Call::close_recovery(..)) | - Call::Recovery(pallet_recovery::Call::remove_recovery(..)) | - Call::Recovery(pallet_recovery::Call::cancel_recovered(..)) | + Call::Recovery(pallet_recovery::Call::as_recovered {..}) | + Call::Recovery(pallet_recovery::Call::vouch_recovery {..}) | + Call::Recovery(pallet_recovery::Call::claim_recovery {..}) | + Call::Recovery(pallet_recovery::Call::close_recovery {..}) | + Call::Recovery(pallet_recovery::Call::remove_recovery {..}) | + Call::Recovery(pallet_recovery::Call::cancel_recovered {..}) | // Specifically omitting Recovery `create_recovery`, `initiate_recovery` - Call::Vesting(pallet_vesting::Call::vest(..)) | - Call::Vesting(pallet_vesting::Call::vest_other(..)) | + Call::Vesting(pallet_vesting::Call::vest {..}) | + Call::Vesting(pallet_vesting::Call::vest_other {..}) | // Specifically omitting Vesting `vested_transfer`, and `force_vested_transfer` Call::Scheduler(..) | Call::Proxy(..) | Call::Multisig(..) | Call::Gilt(..) | - Call::Registrar(paras_registrar::Call::register(..)) | - Call::Registrar(paras_registrar::Call::deregister(..)) | + Call::Registrar(paras_registrar::Call::register {..}) | + Call::Registrar(paras_registrar::Call::deregister {..}) | // Specifically omitting Registrar `swap` - Call::Registrar(paras_registrar::Call::reserve(..)) | + Call::Registrar(paras_registrar::Call::reserve {..}) | Call::Crowdloan(..) | Call::Slots(..) | Call::Auctions(..) // Specifically omitting the entire XCM Pallet @@ -1054,10 +1064,10 @@ impl InstanceFilter for ProxyType { }, ProxyType::IdentityJudgement => matches!( c, - Call::Identity(pallet_identity::Call::provide_judgement(..)) | Call::Utility(..) + Call::Identity(pallet_identity::Call::provide_judgement { .. }) | Call::Utility(..) ), ProxyType::CancelProxy => { - matches!(c, Call::Proxy(pallet_proxy::Call::reject_announcement(..))) + matches!(c, Call::Proxy(pallet_proxy::Call::reject_announcement { .. })) }, ProxyType::Auction => matches!( c, @@ -1118,6 +1128,7 @@ impl parachains_ump::Config for Runtime { type Event = Event; type UmpSink = crate::parachains_ump::XcmSink, Runtime>; type FirstMessageFactorPercent = FirstMessageFactorPercent; + type ExecuteOverweightOrigin = EnsureRoot; } impl parachains_dmp::Config for Runtime {} @@ -1505,11 +1516,66 @@ pub type Executive = frame_executive::Executive< frame_system::ChainContext, Runtime, AllPallets, - (TechnicalMembershipStoragePrefixMigration, MigrateTipsPalletPrefix), + ( + CouncilStoragePrefixMigration, + TechnicalCommitteeStoragePrefixMigration, + TechnicalMembershipStoragePrefixMigration, + MigrateTipsPalletPrefix, + ), >; /// The payload being signed in the transactions. pub type SignedPayload = generic::SignedPayload; +const COUNCIL_OLD_PREFIX: &str = "Instance1Collective"; +/// Migrate from `Instance1Collective` to the new pallet prefix `Council` +pub struct CouncilStoragePrefixMigration; + +impl OnRuntimeUpgrade for CouncilStoragePrefixMigration { + fn on_runtime_upgrade() -> frame_support::weights::Weight { + pallet_collective::migrations::v4::migrate::(COUNCIL_OLD_PREFIX) + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result<(), &'static str> { + pallet_collective::migrations::v4::pre_migrate::(COUNCIL_OLD_PREFIX); + Ok(()) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade() -> Result<(), &'static str> { + pallet_collective::migrations::v4::post_migrate::(COUNCIL_OLD_PREFIX); + Ok(()) + } +} + +const TECHNICAL_COMMITTEE_OLD_PREFIX: &str = "Instance2Collective"; +/// Migrate from `Instance2Collective` to the new pallet prefix `TechnicalCommittee` +pub struct TechnicalCommitteeStoragePrefixMigration; + +impl OnRuntimeUpgrade for TechnicalCommitteeStoragePrefixMigration { + fn on_runtime_upgrade() -> frame_support::weights::Weight { + pallet_collective::migrations::v4::migrate::( + TECHNICAL_COMMITTEE_OLD_PREFIX, + ) + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result<(), &'static str> { + pallet_collective::migrations::v4::pre_migrate::( + TECHNICAL_COMMITTEE_OLD_PREFIX, + ); + Ok(()) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade() -> Result<(), &'static str> { + pallet_collective::migrations::v4::post_migrate::( + TECHNICAL_COMMITTEE_OLD_PREFIX, + ); + Ok(()) + } +} + const TECHNICAL_MEMBERSHIP_OLD_PREFIX: &str = "Instance1Membership"; /// Migrate from `Instance1Membership` to the new pallet prefix `TechnicalMembership` pub struct TechnicalMembershipStoragePrefixMigration; @@ -1590,7 +1656,7 @@ sp_api::impl_runtime_apis! { impl sp_api::Metadata for Runtime { fn metadata() -> OpaqueMetadata { - Runtime::metadata().into() + OpaqueMetadata::new(Runtime::metadata().into()) } } diff --git a/runtime/kusama/src/tests.rs b/runtime/kusama/src/tests.rs index 103987e8b0fd..d2c1c725e3a9 100644 --- a/runtime/kusama/src/tests.rs +++ b/runtime/kusama/src/tests.rs @@ -79,10 +79,10 @@ fn block_cost() { #[ignore] fn transfer_cost_min_multiplier() { let min_multiplier = runtime_common::MinimumMultiplier::get(); - let call = >::transfer_keep_alive( - Default::default(), - Default::default(), - ); + let call = pallet_balances::Call::::transfer_keep_alive { + dest: Default::default(), + value: Default::default(), + }; let info = call.get_dispatch_info(); // convert to outer call. let call = Call::Balances(call); diff --git a/runtime/parachains/Cargo.toml b/runtime/parachains/Cargo.toml index 71c6874428cf..8e3b41d95e6b 100644 --- a/runtime/parachains/Cargo.toml +++ b/runtime/parachains/Cargo.toml @@ -9,7 +9,8 @@ bitvec = { version = "0.20.1", default-features = false, features = ["alloc"] } parity-scale-codec = { version = "2.0.0", default-features = false, features = ["derive"] } log = { version = "0.4.14", default-features = false } rustc-hex = { version = "2.1.0", default-features = false } -serde = { version = "1.0.130", features = ["derive"], optional = true } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } +serde = { version = "1.0.130", features = [ "derive" ], optional = true } derive_more = "0.99.14" bitflags = "1.3.2" @@ -56,6 +57,7 @@ std = [ "bitvec/std", "parity-scale-codec/std", "rustc-hex/std", + "scale-info/std", "serde", "primitives/std", "inherents/std", diff --git a/runtime/parachains/src/configuration.rs b/runtime/parachains/src/configuration.rs index a6cadd158fc7..64aaac6b3487 100644 --- a/runtime/parachains/src/configuration.rs +++ b/runtime/parachains/src/configuration.rs @@ -19,7 +19,7 @@ //! Configuration can change only at session boundaries and is buffered until then. use crate::shared; -use frame_support::pallet_prelude::*; +use frame_support::{pallet_prelude::*, weights::constants::WEIGHT_PER_MILLIS}; use frame_system::pallet_prelude::*; use parity_scale_codec::{Decode, Encode}; use primitives::v1::{Balance, SessionIndex, MAX_CODE_SIZE, MAX_POV_SIZE}; @@ -28,8 +28,12 @@ use sp_std::prelude::*; pub use pallet::*; +pub mod migration; + +const LOG_TARGET: &str = "runtime::configuration"; + /// All configuration of the runtime with respect to parachains and parathreads. -#[derive(Clone, Encode, Decode, PartialEq, sp_core::RuntimeDebug)] +#[derive(Clone, Encode, Decode, PartialEq, sp_core::RuntimeDebug, scale_info::TypeInfo)] #[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] pub struct HostConfiguration { // NOTE: This structure is used by parachains via merkle proofs. Therefore, this struct requires @@ -91,10 +95,6 @@ pub struct HostConfiguration { pub hrmp_max_parachain_outbound_channels: u32, /// The maximum number of outbound HRMP channels a parathread is allowed to open. pub hrmp_max_parathread_outbound_channels: u32, - /// NOTE: this field is deprecated. Channel open requests became non-expiring. Changing this value - /// doesn't have any effect. This field doesn't have a `deprecated` attribute because that would - /// trigger warnings coming from macros. - pub _hrmp_open_request_ttl: u32, /// The deposit that the sender should provide for opening an HRMP channel. pub hrmp_sender_deposit: Balance, /// The deposit that the recipient should provide for accepting opening an HRMP channel. @@ -170,6 +170,9 @@ pub struct HostConfiguration { pub needed_approvals: u32, /// The number of samples to do of the `RelayVRFModulo` approval assignment criterion. pub relay_vrf_modulo_samples: u32, + /// The maximum amount of weight any individual upward message may consume. Messages above this + /// weight go into the overweight queue and may only be serviced explicitly. + pub ump_max_individual_weight: Weight, } impl> Default for HostConfiguration { @@ -204,7 +207,6 @@ impl> Default for HostConfiguration> Default for HostConfiguration(_); #[pallet::config] @@ -764,10 +768,24 @@ pub mod pallet { }); Ok(()) } + + /// Sets the maximum amount of weight any individual upward message may consume. + #[pallet::weight((1_000, DispatchClass::Operational))] + pub fn set_ump_max_individual_weight(origin: OriginFor, new: Weight) -> DispatchResult { + ensure_root(origin)?; + Self::update_config_member(|config| { + sp_std::mem::replace(&mut config.ump_max_individual_weight, new) != new + }); + Ok(()) + } } #[pallet::hooks] impl Hooks> for Pallet { + fn on_runtime_upgrade() -> Weight { + migration::migrate_to_latest::() + } + fn integrity_test() { assert_eq!( &ActiveConfig::::hashed_key(), @@ -888,7 +906,6 @@ mod tests { ump_service_total_weight: 20000, max_upward_message_size: 448, max_upward_message_num_per_candidate: 5, - _hrmp_open_request_ttl: 0, hrmp_sender_deposit: 22, hrmp_recipient_deposit: 4905, hrmp_channel_max_capacity: 3921, @@ -899,6 +916,7 @@ mod tests { hrmp_max_parachain_outbound_channels: 100, hrmp_max_parathread_outbound_channels: 200, hrmp_max_message_num_per_candidate: 20, + ump_max_individual_weight: 909, }; assert!(::PendingConfig::get(shared::SESSION_DELAY).is_none()); @@ -1060,6 +1078,11 @@ mod tests { new_config.hrmp_max_message_num_per_candidate, ) .unwrap(); + Configuration::set_ump_max_individual_weight( + Origin::root(), + new_config.ump_max_individual_weight, + ) + .unwrap(); assert_eq!( ::PendingConfig::get(shared::SESSION_DELAY), diff --git a/runtime/parachains/src/configuration/migration.rs b/runtime/parachains/src/configuration/migration.rs new file mode 100644 index 000000000000..6909eecc15a9 --- /dev/null +++ b/runtime/parachains/src/configuration/migration.rs @@ -0,0 +1,314 @@ +// Copyright 2021 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! A module that is responsible for migration of storage. + +use crate::configuration::{self, Config, Pallet, Store}; +use frame_support::{pallet_prelude::*, traits::StorageVersion, weights::Weight}; +use frame_system::pallet_prelude::BlockNumberFor; + +/// The current storage version. +pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); + +/// Migrates the pallet storage to the most recent version, checking and setting the `StorageVersion`. +pub fn migrate_to_latest() -> Weight { + let mut weight = 0; + + if StorageVersion::get::>() == 0 { + weight += migrate_to_v1::(); + StorageVersion::new(1).put::>(); + } + + weight +} + +mod v0 { + use super::*; + use primitives::v1::{Balance, SessionIndex}; + + #[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug)] + pub struct HostConfiguration { + pub max_code_size: u32, + pub max_head_data_size: u32, + pub max_upward_queue_count: u32, + pub max_upward_queue_size: u32, + pub max_upward_message_size: u32, + pub max_upward_message_num_per_candidate: u32, + pub hrmp_max_message_num_per_candidate: u32, + pub validation_upgrade_frequency: BlockNumber, + pub validation_upgrade_delay: BlockNumber, + pub max_pov_size: u32, + pub max_downward_message_size: u32, + pub ump_service_total_weight: Weight, + pub hrmp_max_parachain_outbound_channels: u32, + pub hrmp_max_parathread_outbound_channels: u32, + pub _hrmp_open_request_ttl: u32, + pub hrmp_sender_deposit: Balance, + pub hrmp_recipient_deposit: Balance, + pub hrmp_channel_max_capacity: u32, + pub hrmp_channel_max_total_size: u32, + pub hrmp_max_parachain_inbound_channels: u32, + pub hrmp_max_parathread_inbound_channels: u32, + pub hrmp_channel_max_message_size: u32, + pub code_retention_period: BlockNumber, + pub parathread_cores: u32, + pub parathread_retries: u32, + pub group_rotation_frequency: BlockNumber, + pub chain_availability_period: BlockNumber, + pub thread_availability_period: BlockNumber, + pub scheduling_lookahead: u32, + pub max_validators_per_core: Option, + pub max_validators: Option, + pub dispute_period: SessionIndex, + pub dispute_post_conclusion_acceptance_period: BlockNumber, + pub dispute_max_spam_slots: u32, + pub dispute_conclusion_by_time_out_period: BlockNumber, + pub no_show_slots: u32, + pub n_delay_tranches: u32, + pub zeroth_delay_tranche_width: u32, + pub needed_approvals: u32, + pub relay_vrf_modulo_samples: u32, + } + + impl> Default for HostConfiguration { + fn default() -> Self { + HostConfiguration { + group_rotation_frequency: 1u32.into(), + chain_availability_period: 1u32.into(), + thread_availability_period: 1u32.into(), + no_show_slots: 1u32.into(), + validation_upgrade_frequency: Default::default(), + validation_upgrade_delay: Default::default(), + code_retention_period: Default::default(), + max_code_size: Default::default(), + max_pov_size: Default::default(), + max_head_data_size: Default::default(), + parathread_cores: Default::default(), + parathread_retries: Default::default(), + scheduling_lookahead: Default::default(), + max_validators_per_core: Default::default(), + max_validators: None, + dispute_period: 6, + dispute_post_conclusion_acceptance_period: 100.into(), + dispute_max_spam_slots: 2, + dispute_conclusion_by_time_out_period: 200.into(), + n_delay_tranches: Default::default(), + zeroth_delay_tranche_width: Default::default(), + needed_approvals: Default::default(), + relay_vrf_modulo_samples: Default::default(), + max_upward_queue_count: Default::default(), + max_upward_queue_size: Default::default(), + max_downward_message_size: Default::default(), + ump_service_total_weight: Default::default(), + max_upward_message_size: Default::default(), + max_upward_message_num_per_candidate: Default::default(), + _hrmp_open_request_ttl: Default::default(), + hrmp_sender_deposit: Default::default(), + hrmp_recipient_deposit: Default::default(), + hrmp_channel_max_capacity: Default::default(), + hrmp_channel_max_total_size: Default::default(), + hrmp_max_parachain_inbound_channels: Default::default(), + hrmp_max_parathread_inbound_channels: Default::default(), + hrmp_channel_max_message_size: Default::default(), + hrmp_max_parachain_outbound_channels: Default::default(), + hrmp_max_parathread_outbound_channels: Default::default(), + hrmp_max_message_num_per_candidate: Default::default(), + } + } + } +} + +/// Migrates the `HostConfiguration` from v0 (with deprecated `hrmp_open_request_ttl` and without +/// `ump_max_individual_weight`) to v1 (without HRMP TTL and with max individual weight). +/// Uses the `Default` implementation of `HostConfiguration` to choose a value for `ump_max_individual_weight`. +/// +/// NOTE: Only use this function if you know what you are doing. Default to using `migrate_to_latest`. +pub fn migrate_to_v1() -> Weight { + // Unusual formatting is justified: + // - make it easier to verify that fields assign what they supposed to assign. + // - this code is transient and will be removed after all migrations are done. + // - this code is important enough to optimize for legibility sacrificing consistency. + #[rustfmt::skip] + let translate = + |pre: v0::HostConfiguration>| -> configuration::HostConfiguration> + { + super::HostConfiguration { + +max_code_size : pre.max_code_size, +max_head_data_size : pre.max_head_data_size, +max_upward_queue_count : pre.max_upward_queue_count, +max_upward_queue_size : pre.max_upward_queue_size, +max_upward_message_size : pre.max_upward_message_size, +max_upward_message_num_per_candidate : pre.max_upward_message_num_per_candidate, +hrmp_max_message_num_per_candidate : pre.hrmp_max_message_num_per_candidate, +validation_upgrade_frequency : pre.validation_upgrade_frequency, +validation_upgrade_delay : pre.validation_upgrade_delay, +max_pov_size : pre.max_pov_size, +max_downward_message_size : pre.max_downward_message_size, +ump_service_total_weight : pre.ump_service_total_weight, +hrmp_max_parachain_outbound_channels : pre.hrmp_max_parachain_outbound_channels, +hrmp_max_parathread_outbound_channels : pre.hrmp_max_parathread_outbound_channels, +hrmp_sender_deposit : pre.hrmp_sender_deposit, +hrmp_recipient_deposit : pre.hrmp_recipient_deposit, +hrmp_channel_max_capacity : pre.hrmp_channel_max_capacity, +hrmp_channel_max_total_size : pre.hrmp_channel_max_total_size, +hrmp_max_parachain_inbound_channels : pre.hrmp_max_parachain_inbound_channels, +hrmp_max_parathread_inbound_channels : pre.hrmp_max_parathread_inbound_channels, +hrmp_channel_max_message_size : pre.hrmp_channel_max_message_size, +code_retention_period : pre.code_retention_period, +parathread_cores : pre.parathread_cores, +parathread_retries : pre.parathread_retries, +group_rotation_frequency : pre.group_rotation_frequency, +chain_availability_period : pre.chain_availability_period, +thread_availability_period : pre.thread_availability_period, +scheduling_lookahead : pre.scheduling_lookahead, +max_validators_per_core : pre.max_validators_per_core, +max_validators : pre.max_validators, +dispute_period : pre.dispute_period, +dispute_post_conclusion_acceptance_period: pre.dispute_post_conclusion_acceptance_period, +dispute_max_spam_slots : pre.dispute_max_spam_slots, +dispute_conclusion_by_time_out_period : pre.dispute_conclusion_by_time_out_period, +no_show_slots : pre.no_show_slots, +n_delay_tranches : pre.n_delay_tranches, +zeroth_delay_tranche_width : pre.zeroth_delay_tranche_width, +needed_approvals : pre.needed_approvals, +relay_vrf_modulo_samples : pre.relay_vrf_modulo_samples, + +ump_max_individual_weight: >>::default().ump_max_individual_weight, + } + }; + + if let Err(_) = as Store>::ActiveConfig::translate(|pre| pre.map(translate)) { + // `Err` is returned when the pre-migration type cannot be deserialized. This + // cannot happen if the migration runs correctly, i.e. against the expected version. + // + // This happening almost surely will lead to a panic somewhere else. Corruption seems + // to be unlikely to be caused by this. So we just log. Maybe it'll work out still? + log::error!( + target: configuration::LOG_TARGET, + "unexpected error when performing translation of the configuration type during storage upgrade to v1." + ); + } + + T::DbWeight::get().reads_writes(1, 1) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::{new_test_ext, Test}; + + #[test] + fn v0_deserialized_from_actual_data() { + // Fetched at Kusama 9,207,703 (0xbfe5227324c08b3ab67e0473a360acbce43efbd7b42041d0033adaf9ff2c5330) + // + // This exceeds the maximal line width length, but that's fine, since this is not code and + // doesn't need to be read and also leaving it as one line allows to easily copy it. + let raw_config = hex_literal::hex!["0000a000005000000a00000000c8000000c800000a0000000a00000040380000580200000000500000c8000000e87648170000000a0000000000000048000000c09e5d9a2f3d00000000000000000000c09e5d9a2f3d00000000000000000000e8030000009001000a00000000000000009001008070000000000000000000000a0000000a0000000a00000001000000010500000001c8000000060000005802000002000000580200000200000059000000000000001e00000028000000"]; + + let v0 = v0::HostConfiguration::::decode(&mut &raw_config[..]) + .unwrap(); + + // We check only a sample of the values here. If we missed any fields or messed up data types + // that would skew all the fields coming after. + assert_eq!(v0.max_code_size, 10_485_760); + assert_eq!(v0.validation_upgrade_frequency, 14_400); + assert_eq!(v0.max_pov_size, 5_242_880); + assert_eq!(v0._hrmp_open_request_ttl, 72); + assert_eq!(v0.hrmp_channel_max_message_size, 102_400); + assert_eq!(v0.dispute_max_spam_slots, 2); + assert_eq!(v0.n_delay_tranches, 89); + assert_eq!(v0.relay_vrf_modulo_samples, 40); + } + + #[test] + fn test_migrate_to_v1() { + // Host configuration has lots of fields. However, in this migration we add one and remove one + // field. The most important part to check are a couple of the last fields. We also pick + // extra fields to check arbitrarily, e.g. depending on their position (i.e. the middle) and + // also their type. + // + // We specify only the picked fields and the rest should be provided by the `Default` + // implementation. That implementation is copied over between the two types and should work + // fine. + let v0 = v0::HostConfiguration:: { + relay_vrf_modulo_samples: 0xFEEDBEEFu32, + needed_approvals: 69, + thread_availability_period: 55, + hrmp_recipient_deposit: 1337, + max_pov_size: 1111, + ..Default::default() + }; + + new_test_ext(Default::default()).execute_with(|| { + // Implant the v0 version in the state. + frame_support::storage::unhashed::put_raw( + &configuration::ActiveConfig::::hashed_key(), + &v0.encode(), + ); + + migrate_to_v1::(); + + let v1 = configuration::ActiveConfig::::get(); + + // The same motivation as for the migration code. See `migrate_to_v1`. + #[rustfmt::skip] + { + assert_eq!(v0.max_code_size , v1.max_code_size); + assert_eq!(v0.max_head_data_size , v1.max_head_data_size); + assert_eq!(v0.max_upward_queue_count , v1.max_upward_queue_count); + assert_eq!(v0.max_upward_queue_size , v1.max_upward_queue_size); + assert_eq!(v0.max_upward_message_size , v1.max_upward_message_size); + assert_eq!(v0.max_upward_message_num_per_candidate , v1.max_upward_message_num_per_candidate); + assert_eq!(v0.hrmp_max_message_num_per_candidate , v1.hrmp_max_message_num_per_candidate); + assert_eq!(v0.validation_upgrade_frequency , v1.validation_upgrade_frequency); + assert_eq!(v0.validation_upgrade_delay , v1.validation_upgrade_delay); + assert_eq!(v0.max_pov_size , v1.max_pov_size); + assert_eq!(v0.max_downward_message_size , v1.max_downward_message_size); + assert_eq!(v0.ump_service_total_weight , v1.ump_service_total_weight); + assert_eq!(v0.hrmp_max_parachain_outbound_channels , v1.hrmp_max_parachain_outbound_channels); + assert_eq!(v0.hrmp_max_parathread_outbound_channels , v1.hrmp_max_parathread_outbound_channels); + assert_eq!(v0.hrmp_sender_deposit , v1.hrmp_sender_deposit); + assert_eq!(v0.hrmp_recipient_deposit , v1.hrmp_recipient_deposit); + assert_eq!(v0.hrmp_channel_max_capacity , v1.hrmp_channel_max_capacity); + assert_eq!(v0.hrmp_channel_max_total_size , v1.hrmp_channel_max_total_size); + assert_eq!(v0.hrmp_max_parachain_inbound_channels , v1.hrmp_max_parachain_inbound_channels); + assert_eq!(v0.hrmp_max_parathread_inbound_channels , v1.hrmp_max_parathread_inbound_channels); + assert_eq!(v0.hrmp_channel_max_message_size , v1.hrmp_channel_max_message_size); + assert_eq!(v0.code_retention_period , v1.code_retention_period); + assert_eq!(v0.parathread_cores , v1.parathread_cores); + assert_eq!(v0.parathread_retries , v1.parathread_retries); + assert_eq!(v0.group_rotation_frequency , v1.group_rotation_frequency); + assert_eq!(v0.chain_availability_period , v1.chain_availability_period); + assert_eq!(v0.thread_availability_period , v1.thread_availability_period); + assert_eq!(v0.scheduling_lookahead , v1.scheduling_lookahead); + assert_eq!(v0.max_validators_per_core , v1.max_validators_per_core); + assert_eq!(v0.max_validators , v1.max_validators); + assert_eq!(v0.dispute_period , v1.dispute_period); + assert_eq!(v0.dispute_post_conclusion_acceptance_period, v1.dispute_post_conclusion_acceptance_period); + assert_eq!(v0.dispute_max_spam_slots , v1.dispute_max_spam_slots); + assert_eq!(v0.dispute_conclusion_by_time_out_period , v1.dispute_conclusion_by_time_out_period); + assert_eq!(v0.no_show_slots , v1.no_show_slots); + assert_eq!(v0.n_delay_tranches , v1.n_delay_tranches); + assert_eq!(v0.zeroth_delay_tranche_width , v1.zeroth_delay_tranche_width); + assert_eq!(v0.needed_approvals , v1.needed_approvals); + assert_eq!(v0.relay_vrf_modulo_samples , v1.relay_vrf_modulo_samples); + + assert_eq!(v1.ump_max_individual_weight, 20_000_000_000); + }; // ; makes this a statement. `rustfmt::skip` cannot be put on an expression. + }); + } +} diff --git a/runtime/parachains/src/disputes.rs b/runtime/parachains/src/disputes.rs index 43388c64b01c..b3bd5a3ed68d 100644 --- a/runtime/parachains/src/disputes.rs +++ b/runtime/parachains/src/disputes.rs @@ -30,6 +30,7 @@ use primitives::v1::{ InvalidDisputeStatementKind, MultiDisputeStatementSet, SessionIndex, SigningContext, ValidDisputeStatementKind, ValidatorId, ValidatorIndex, ValidatorSignature, }; +use scale_info::TypeInfo; use sp_runtime::{ traits::{AppVerify, One, Saturating, Zero}, DispatchError, RuntimeDebug, SaturatedConversion, @@ -37,14 +38,14 @@ use sp_runtime::{ use sp_std::{collections::btree_set::BTreeSet, prelude::*}; /// Whether the dispute is local or remote. -#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] pub enum DisputeLocation { Local, Remote, } /// The result of a dispute, whether the candidate is deemed valid (for) or invalid (against). -#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] pub enum DisputeResult { Valid, Invalid, diff --git a/runtime/parachains/src/hrmp.rs b/runtime/parachains/src/hrmp.rs index bb200900d5b5..f087dfd3a405 100644 --- a/runtime/parachains/src/hrmp.rs +++ b/runtime/parachains/src/hrmp.rs @@ -25,6 +25,7 @@ use primitives::v1::{ Balance, Hash, HrmpChannelId, Id as ParaId, InboundHrmpMessage, OutboundHrmpMessage, SessionIndex, }; +use scale_info::TypeInfo; use sp_runtime::traits::{AccountIdConversion, BlakeTwo256, Hash as HashT, UniqueSaturatedInto}; use sp_std::{ collections::{btree_map::BTreeMap, btree_set::BTreeSet}, @@ -35,7 +36,7 @@ use sp_std::{ pub use pallet::*; /// A description of a request to open an HRMP channel. -#[derive(Encode, Decode)] +#[derive(Encode, Decode, TypeInfo)] pub struct HrmpOpenChannelRequest { /// Indicates if this request was confirmed by the recipient. pub confirmed: bool, @@ -53,7 +54,7 @@ pub struct HrmpOpenChannelRequest { } /// A metadata of an HRMP channel. -#[derive(Encode, Decode)] +#[derive(Encode, Decode, TypeInfo)] #[cfg_attr(test, derive(Debug))] pub struct HrmpChannel { // NOTE: This structure is used by parachains via merkle proofs. Therefore, this struct requires diff --git a/runtime/parachains/src/inclusion.rs b/runtime/parachains/src/inclusion.rs index 4d92e90df734..a8702c873c2f 100644 --- a/runtime/parachains/src/inclusion.rs +++ b/runtime/parachains/src/inclusion.rs @@ -28,6 +28,7 @@ use primitives::v1::{ CandidateHash, CandidateReceipt, CommittedCandidateReceipt, CoreIndex, GroupIndex, HeadData, Id as ParaId, SigningContext, UncheckedSignedAvailabilityBitfields, ValidatorIndex, }; +use scale_info::TypeInfo; use sp_runtime::{ traits::{One, Saturating}, DispatchError, @@ -43,7 +44,7 @@ pub use pallet::*; /// /// The bitfield's signature should be checked at the point of submission. Afterwards it can be /// dropped. -#[derive(Encode, Decode)] +#[derive(Encode, Decode, TypeInfo)] #[cfg_attr(test, derive(Debug))] pub struct AvailabilityBitfieldRecord { bitfield: AvailabilityBitfield, // one bit per core. @@ -51,7 +52,7 @@ pub struct AvailabilityBitfieldRecord { } /// A backed candidate pending availability. -#[derive(Encode, Decode, PartialEq)] +#[derive(Encode, Decode, PartialEq, TypeInfo)] #[cfg_attr(test, derive(Debug))] pub struct CandidatePendingAvailability { /// The availability core this is assigned to. @@ -134,7 +135,6 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] - #[pallet::metadata(T::Hash = "Hash")] pub enum Event { /// A candidate was backed. `[candidate, head_data]` CandidateBacked(CandidateReceipt, HeadData, CoreIndex, GroupIndex), diff --git a/runtime/parachains/src/initializer.rs b/runtime/parachains/src/initializer.rs index dc47ccc79864..6958d754c462 100644 --- a/runtime/parachains/src/initializer.rs +++ b/runtime/parachains/src/initializer.rs @@ -27,6 +27,7 @@ use crate::{ use frame_support::traits::{OneSessionHandler, Randomness}; use parity_scale_codec::{Decode, Encode}; use primitives::v1::{BlockNumber, ConsensusLog, SessionIndex, ValidatorId}; +use scale_info::TypeInfo; use sp_std::prelude::*; pub use pallet::*; @@ -61,7 +62,7 @@ impl> Default for SessionChangeNotification, queued: Vec, diff --git a/runtime/parachains/src/mock.rs b/runtime/parachains/src/mock.rs index 88e241426d62..5cf8d6237485 100644 --- a/runtime/parachains/src/mock.rs +++ b/runtime/parachains/src/mock.rs @@ -133,6 +133,7 @@ impl crate::ump::Config for Test { type Event = Event; type UmpSink = TestUmpSink; type FirstMessageFactorPercent = FirstMessageFactorPercent; + type ExecuteOverweightOrigin = frame_system::EnsureRoot; } impl crate::hrmp::Config for Test { @@ -309,3 +310,11 @@ pub struct MockGenesisConfig { pub configuration: crate::configuration::GenesisConfig, pub paras: crate::paras::GenesisConfig, } + +pub fn assert_last_event(generic_event: Event) { + let events = frame_system::Pallet::::events(); + let system_event: ::Event = generic_event.into(); + // compare to the last event record + let frame_system::EventRecord { event, .. } = &events[events.len() - 1]; + assert_eq!(event, &system_event); +} diff --git a/runtime/parachains/src/origin.rs b/runtime/parachains/src/origin.rs index ba4ad549c78e..83d4dcc25d99 100644 --- a/runtime/parachains/src/origin.rs +++ b/runtime/parachains/src/origin.rs @@ -54,7 +54,7 @@ pub mod pallet { /// Origin for the parachains. #[pallet::origin] - #[derive(PartialEq, Eq, Clone, Encode, Decode, sp_core::RuntimeDebug)] + #[derive(PartialEq, Eq, Clone, Encode, Decode, sp_core::RuntimeDebug, scale_info::TypeInfo)] pub enum Origin { /// It comes from a parachain. Parachain(ParaId), diff --git a/runtime/parachains/src/paras.rs b/runtime/parachains/src/paras.rs index 170914d8f518..9a840837ae94 100644 --- a/runtime/parachains/src/paras.rs +++ b/runtime/parachains/src/paras.rs @@ -31,6 +31,7 @@ use primitives::v1::{ ConsensusLog, HeadData, Id as ParaId, SessionIndex, UpgradeGoAhead, UpgradeRestriction, ValidationCode, ValidationCodeHash, }; +use scale_info::TypeInfo; use sp_core::RuntimeDebug; use sp_runtime::{traits::One, DispatchResult, SaturatedConversion}; use sp_std::{prelude::*, result}; @@ -43,7 +44,7 @@ pub use crate::Origin as ParachainOrigin; pub use pallet::*; // the two key times necessary to track for every code replacement. -#[derive(Default, Encode, Decode)] +#[derive(Default, Encode, Decode, TypeInfo)] #[cfg_attr(test, derive(Debug, Clone, PartialEq))] pub struct ReplacementTimes { /// The relay-chain block number that the code upgrade was expected to be activated. @@ -58,7 +59,7 @@ pub struct ReplacementTimes { /// Metadata used to track previous parachain validation code that we keep in /// the state. -#[derive(Default, Encode, Decode)] +#[derive(Default, Encode, Decode, TypeInfo)] #[cfg_attr(test, derive(Debug, Clone, PartialEq))] pub struct ParaPastCodeMeta { /// Block numbers where the code was expected to be replaced and where the code @@ -87,7 +88,7 @@ enum UseCodeAt { /// If the para is in a "transition state", it is expected that the parachain is /// queued in the `ActionsQueue` to transition it into a stable state. Its lifecycle /// state will be used to determine the state transition to apply to the para. -#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)] +#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo)] pub enum ParaLifecycle { /// Para is new and is onboarding as a Parathread or Parachain. Onboarding, @@ -255,7 +256,7 @@ impl ParaPastCodeMeta { } /// Arguments for initializing a para. -#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)] +#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct ParaGenesisArgs { /// The initial head data to use. diff --git a/runtime/parachains/src/paras_inherent.rs b/runtime/parachains/src/paras_inherent.rs index 82e21cbe1805..e2dd357658df 100644 --- a/runtime/parachains/src/paras_inherent.rs +++ b/runtime/parachains/src/paras_inherent.rs @@ -135,11 +135,11 @@ pub mod pallet { }, }; - Some(Call::enter(inherent_data)) + Some(Call::enter { data: inherent_data }) } fn is_inherent(call: &Self::Call) -> bool { - matches!(call, Call::enter(..)) + matches!(call, Call::enter { .. }) } } @@ -429,12 +429,14 @@ mod tests { System::set_block_consumed_resources(used_block_weight, 0); // execute the paras inherent - let post_info = Call::::enter(ParachainsInherentData { - bitfields: signed_bitfields, - backed_candidates, - disputes: Vec::new(), - parent_header: default_header(), - }) + let post_info = Call::::enter { + data: ParachainsInherentData { + bitfields: signed_bitfields, + backed_candidates, + disputes: Vec::new(), + parent_header: default_header(), + }, + } .dispatch_bypass_filter(None.into()) .unwrap_err() .post_info; @@ -477,12 +479,14 @@ mod tests { System::set_block_consumed_resources(used_block_weight, 0); // execute the paras inherent - let post_info = Call::::enter(ParachainsInherentData { - bitfields: signed_bitfields, - backed_candidates, - disputes: Vec::new(), - parent_header: header, - }) + let post_info = Call::::enter { + data: ParachainsInherentData { + bitfields: signed_bitfields, + backed_candidates, + disputes: Vec::new(), + parent_header: header, + }, + } .dispatch_bypass_filter(None.into()) .unwrap(); diff --git a/runtime/parachains/src/scheduler.rs b/runtime/parachains/src/scheduler.rs index ef06fb79beba..e6772c19d910 100644 --- a/runtime/parachains/src/scheduler.rs +++ b/runtime/parachains/src/scheduler.rs @@ -40,6 +40,7 @@ use primitives::v1::{ CollatorId, CoreIndex, CoreOccupied, GroupIndex, GroupRotationInfo, Id as ParaId, ParathreadClaim, ParathreadEntry, ScheduledCore, ValidatorIndex, }; +use scale_info::TypeInfo; use sp_runtime::traits::{One, Saturating}; use sp_std::{convert::TryInto, prelude::*}; @@ -48,7 +49,7 @@ use crate::{configuration, initializer::SessionChangeNotification, paras}; pub use pallet::*; /// A queued parathread entry, pre-assigned to a core. -#[derive(Encode, Decode, Default)] +#[derive(Encode, Decode, Default, TypeInfo)] #[cfg_attr(test, derive(PartialEq, Debug))] pub struct QueuedParathread { claim: ParathreadEntry, @@ -56,7 +57,7 @@ pub struct QueuedParathread { } /// The queue of all parathread claims. -#[derive(Encode, Decode, Default)] +#[derive(Encode, Decode, Default, TypeInfo)] #[cfg_attr(test, derive(PartialEq, Debug))] pub struct ParathreadClaimQueue { queue: Vec, @@ -97,7 +98,7 @@ pub enum FreedReason { } /// The assignment type. -#[derive(Clone, Encode, Decode)] +#[derive(Clone, Encode, Decode, TypeInfo)] #[cfg_attr(feature = "std", derive(PartialEq, Debug))] pub enum AssignmentKind { /// A parachain. @@ -107,7 +108,7 @@ pub enum AssignmentKind { } /// How a free core is scheduled to be assigned. -#[derive(Clone, Encode, Decode)] +#[derive(Clone, Encode, Decode, TypeInfo)] #[cfg_attr(feature = "std", derive(PartialEq, Debug))] pub struct CoreAssignment { /// The core that is assigned. diff --git a/runtime/parachains/src/session_info.rs b/runtime/parachains/src/session_info.rs index 3e18b16b9aab..93f0ba736577 100644 --- a/runtime/parachains/src/session_info.rs +++ b/runtime/parachains/src/session_info.rs @@ -19,7 +19,10 @@ //! //! See https://w3f.github.io/parachain-implementers-guide/runtime/session_info.html. -use crate::{configuration, paras, scheduler, shared, util::take_active_subset}; +use crate::{ + configuration, paras, scheduler, shared, + util::{take_active_subset, take_active_subset_and_inactive}, +}; use frame_support::{pallet_prelude::*, traits::OneSessionHandler}; use primitives::v1::{AssignmentId, AuthorityDiscoveryId, SessionIndex, SessionInfo}; use sp_std::vec::Vec; @@ -120,7 +123,7 @@ impl Pallet { // create a new entry in `Sessions` with information about the current session let new_session_info = SessionInfo { validators, // these are from the notification and are thus already correct. - discovery_keys: take_active_subset(&active_set, &discovery_keys), + discovery_keys: take_active_subset_and_inactive(&active_set, &discovery_keys), assignment_keys: take_active_subset(&active_set, &assignment_keys), validator_groups, n_cores, @@ -176,6 +179,7 @@ mod tests { new_test_ext, Configuration, MockGenesisConfig, Origin, ParasShared, SessionInfo, System, Test, }, + util::take_active_subset, }; use keyring::Sr25519Keyring; use primitives::v1::{BlockNumber, ValidatorId, ValidatorIndex}; @@ -357,7 +361,7 @@ mod tests { assert_eq!(session.validators, validators); assert_eq!( session.discovery_keys, - take_active_subset(&active_set, &unscrambled_discovery), + take_active_subset_and_inactive(&active_set, &unscrambled_discovery), ); assert_eq!( session.assignment_keys, diff --git a/runtime/parachains/src/ump.rs b/runtime/parachains/src/ump.rs index ae04d2d460df..a4f046024802 100644 --- a/runtime/parachains/src/ump.rs +++ b/runtime/parachains/src/ump.rs @@ -18,10 +18,11 @@ use crate::{ configuration::{self, HostConfiguration}, initializer, }; -use frame_support::pallet_prelude::*; +use frame_support::{pallet_prelude::*, traits::EnsureOrigin}; +use frame_system::pallet_prelude::*; use primitives::v1::{Id as ParaId, UpwardMessage}; use sp_std::{ - collections::btree_map::BTreeMap, convert::TryFrom, fmt, marker::PhantomData, prelude::*, + collections::btree_map::BTreeMap, convert::TryFrom, fmt, marker::PhantomData, mem, prelude::*, }; use xcm::latest::Outcome; @@ -70,10 +71,18 @@ impl UmpSink for () { /// if the message content is unique. pub type MessageId = [u8; 32]; +/// Index used to identify overweight messages. +pub type OverweightIndex = u64; + /// A specific implementation of a `UmpSink` where messages are in the XCM format /// and will be forwarded to the XCM Executor. pub struct XcmSink(PhantomData<(XcmExecutor, Config)>); +/// Returns a [`MessageId`] for the given upward message payload. +fn upward_message_id(data: &[u8]) -> MessageId { + sp_io::hashing::blake2_256(data) +} + impl, C: Config> UmpSink for XcmSink { fn process_upward_message( origin: ParaId, @@ -86,7 +95,7 @@ impl, C: Config> UmpSink for XcmSi VersionedXcm, }; - let id = sp_io::hashing::blake2_256(&data[..]); + let id = upward_message_id(&data[..]); let maybe_msg = VersionedXcm::::decode_all_with_depth_limit( xcm::MAX_XCM_DECODE_DEPTH, &mut &data[..], @@ -177,6 +186,9 @@ pub mod pallet { /// /// Generally you'll want this to be a bit more - 150 or 200 would be good values. type FirstMessageFactorPercent: Get; + + /// Origin which is allowed to execute overweight messages. + type ExecuteOverweightOrigin: EnsureOrigin; } #[pallet::event] @@ -197,6 +209,26 @@ pub mod pallet { /// Some downward messages have been received and will be processed. /// \[ para, count, size \] UpwardMessagesReceived(ParaId, u32, u32), + /// The weight budget was exceeded for an individual downward message. + /// + /// This message can be later dispatched manually using `service_overweight` dispatchable + /// using the assigned `overweight_index`. + /// + /// \[ para, id, overweight_index, required \] + OverweightEnqueued(ParaId, MessageId, OverweightIndex, Weight), + /// Downward message from the overweight queue was executed with the given actual weight + /// used. + /// + /// \[ overweight_index, used \] + OverweightServiced(OverweightIndex, Weight), + } + + #[pallet::error] + pub enum Error { + /// The message index given is unknown. + UnknownMessageIndex, + /// The amount of weight given is possibly not enough for executing the message. + WeightOverLimit, } /// The messages waiting to be handled by the relay-chain originating from a certain parachain. @@ -242,8 +274,49 @@ pub mod pallet { #[pallet::storage] pub type NextDispatchRoundStartWith = StorageValue<_, ParaId>; + /// The messages that exceeded max individual message weight budget. + /// + /// These messages stay there until manually dispatched. + #[pallet::storage] + pub type Overweight = + StorageMap<_, Twox64Concat, OverweightIndex, (ParaId, Vec), OptionQuery>; + + /// The number of overweight messages ever recorded in `Overweight` (and thus the lowest free + /// index). + #[pallet::storage] + pub type OverweightCount = StorageValue<_, OverweightIndex, ValueQuery>; + #[pallet::call] - impl Pallet {} + impl Pallet { + /// Service a single overweight upward message. + /// + /// - `origin`: Must pass `ExecuteOverweightOrigin`. + /// - `index`: The index of the overweight message to service. + /// - `weight_limit`: The amount of weight that message execution may take. + /// + /// Errors: + /// - `UnknownMessageIndex`: Message of `index` is unknown. + /// - `WeightOverLimit`: Message execution may use greater than `weight_limit`. + /// + /// Events: + /// - `OverweightServiced`: On success. + #[pallet::weight(weight_limit.saturating_add(1_000_000))] + pub fn service_overweight( + origin: OriginFor, + index: OverweightIndex, + weight_limit: Weight, + ) -> DispatchResultWithPostInfo { + T::ExecuteOverweightOrigin::ensure_origin(origin)?; + + let (sender, data) = + Overweight::::get(index).ok_or(Error::::UnknownMessageIndex)?; + let used = T::UmpSink::process_upward_message(sender, &data[..], weight_limit) + .map_err(|_| Error::::WeightOverLimit)?; + Overweight::::remove(index); + Self::deposit_event(Event::OverweightServiced(index, used)); + Ok(Some(used.saturating_add(1_000_000)).into()) + } + } } /// Routines related to the upward message passing. @@ -406,26 +479,36 @@ impl Pallet { // attempt to process the next message from the queue of the dispatchee; if not beyond // our remaining weight limit, then consume it. let maybe_next = queue_cache.peek_front::(dispatchee); - let became_empty = if let Some(upward_message) = maybe_next { + if let Some(upward_message) = maybe_next { match T::UmpSink::process_upward_message(dispatchee, upward_message, max_weight) { Ok(used) => { weight_used += used; - queue_cache.consume_front::(dispatchee) + let _ = queue_cache.consume_front::(dispatchee); }, Err((id, required)) => { - // we process messages in order and don't drop them if we run out of weight, - // so need to break here without calling `consume_front`. - Self::deposit_event(Event::WeightExhausted(id, max_weight, required)); - break + if required > config.ump_max_individual_weight { + // overweight - add to overweight queue and continue with message + // execution consuming the message. + let upward_message = queue_cache.consume_front::(dispatchee).expect( + "`consume_front` should return the same msg as `peek_front`;\ + if we get into this branch then `peek_front` returned `Some`;\ + thus `upward_message` cannot be `None`; qed", + ); + let index = Self::stash_overweight(dispatchee, upward_message); + Self::deposit_event(Event::OverweightEnqueued( + dispatchee, id, index, required, + )); + } else { + // we process messages in order and don't drop them if we run out of weight, + // so need to break here without calling `consume_front`. + Self::deposit_event(Event::WeightExhausted(id, max_weight, required)); + break + } }, } - } else { - // this should never happen, since the cursor should never point to an empty queue. - // it is resolved harmlessly here anyway. - true - }; + } - if became_empty { + if queue_cache.is_empty::(dispatchee) { // the queue is empty now - this para doesn't need attention anymore. cursor.remove(); } else { @@ -438,6 +521,19 @@ impl Pallet { weight_used } + + /// Puts a given upward message into the list of overweight messages allowing it to be executed + /// later. + fn stash_overweight(sender: ParaId, upward_message: Vec) -> OverweightIndex { + let index = ::OverweightCount::mutate(|count| { + let index = *count; + *count += 1; + index + }); + + ::Overweight::insert(index, (sender, upward_message)); + index + } } /// To avoid constant fetching, deserializing and serialization the queues are cached. @@ -490,16 +586,27 @@ impl QueueCache { /// Attempts to remove one message from the front of `para`'s queue. If the queue is empty, then /// does nothing. - /// - /// Returns `true` iff there are no more messages in the queue after the removal attempt. - fn consume_front(&mut self, para: ParaId) -> bool { + fn consume_front(&mut self, para: ParaId) -> Option { let cache_entry = self.ensure_cached::(para); - let upward_message = cache_entry.queue.get(cache_entry.consumed_count); - if let Some(msg) = upward_message { - cache_entry.consumed_count += 1; - cache_entry.consumed_size += msg.len(); + + match cache_entry.queue.get_mut(cache_entry.consumed_count) { + Some(msg) => { + cache_entry.consumed_count += 1; + cache_entry.consumed_size += msg.len(); + + Some(mem::take(msg)) + }, + None => None, } + } + /// Returns if the queue for the given para is empty. + /// + /// That is, if this returns `true` then the next call to [`peek_front`] will return `None`. + /// + /// Does not mutate the queue. + fn is_empty(&mut self, para: ParaId) -> bool { + let cache_entry = self.ensure_cached::(para); cache_entry.consumed_count >= cache_entry.queue.len() } @@ -600,8 +707,11 @@ impl NeedsDispatchCursor { #[cfg(test)] pub(crate) mod tests { use super::*; - use crate::mock::{new_test_ext, take_processed, Configuration, MockGenesisConfig, Ump}; - use frame_support::weights::Weight; + use crate::mock::{ + assert_last_event, new_test_ext, take_processed, Configuration, MockGenesisConfig, Origin, + System, Test, Ump, + }; + use frame_support::{assert_noop, assert_ok, weights::Weight}; use std::collections::HashSet; struct GenesisConfigBuilder { @@ -610,6 +720,7 @@ pub(crate) mod tests { max_upward_queue_count: u32, max_upward_queue_size: u32, ump_service_total_weight: Weight, + ump_max_individual_weight: Weight, } impl Default for GenesisConfigBuilder { @@ -620,6 +731,7 @@ pub(crate) mod tests { max_upward_queue_count: 4, max_upward_queue_size: 64, ump_service_total_weight: 1000, + ump_max_individual_weight: 100, } } } @@ -634,6 +746,7 @@ pub(crate) mod tests { config.max_upward_queue_count = self.max_upward_queue_count; config.max_upward_queue_size = self.max_upward_queue_size; config.ump_service_total_weight = self.ump_service_total_weight; + config.ump_max_individual_weight = self.ump_max_individual_weight; genesis } } @@ -778,7 +891,12 @@ pub(crate) mod tests { let a_msg_2 = (300u32, "a_msg_2").encode(); new_test_ext( - GenesisConfigBuilder { ump_service_total_weight: 500, ..Default::default() }.build(), + GenesisConfigBuilder { + ump_service_total_weight: 500, + ump_max_individual_weight: 300, + ..Default::default() + } + .build(), ) .execute_with(|| { queue_upward_msg(a, a_msg_1.clone()); @@ -856,4 +974,71 @@ pub(crate) mod tests { assert_eq!(size, 3); }); } + + #[test] + fn service_overweight_unknown() { + // This test just makes sure that 0 is not a valid index and we can use it not worrying in + // the next test. + new_test_ext(GenesisConfigBuilder::default().build()).execute_with(|| { + assert_noop!( + Ump::service_overweight(Origin::root(), 0, 1000), + Error::::UnknownMessageIndex + ); + }); + } + + #[test] + fn overweight_queue_works() { + let para_a = ParaId::from(2021); + + let a_msg_1 = (301u32, "a_msg_1").encode(); + let a_msg_2 = (500u32, "a_msg_2").encode(); + let a_msg_3 = (500u32, "a_msg_3").encode(); + + new_test_ext( + GenesisConfigBuilder { + ump_service_total_weight: 900, + ump_max_individual_weight: 300, + ..Default::default() + } + .build(), + ) + .execute_with(|| { + // HACK: Start with the block number 1. This is needed because should an event be + // emitted during the genesis block they will be implicitly wiped. + System::set_block_number(1); + + // This one is overweight. However, the weight is plenty and we can afford to execute + // this message, thus expect it. + queue_upward_msg(para_a, a_msg_1.clone()); + Ump::process_pending_upward_messages(); + assert_eq!(take_processed(), vec![(para_a, a_msg_1)]); + + // This is overweight and this message cannot fit into the total weight budget. + queue_upward_msg(para_a, a_msg_2.clone()); + queue_upward_msg(para_a, a_msg_3.clone()); + Ump::process_pending_upward_messages(); + assert_last_event( + Event::OverweightEnqueued(para_a, upward_message_id(&a_msg_3[..]), 0, 500).into(), + ); + + // Now verify that if we wanted to service this overweight message with less than enough + // weight it will fail. + assert_noop!( + Ump::service_overweight(Origin::root(), 0, 499), + Error::::WeightOverLimit + ); + + // ... and if we try to service it with just enough weight it will succeed as well. + assert_ok!(Ump::service_overweight(Origin::root(), 0, 500)); + assert_last_event(Event::OverweightServiced(0, 500).into()); + + // ... and if we try to service a message with index that doesn't exist it will error + // out. + assert_noop!( + Ump::service_overweight(Origin::root(), 1, 1000), + Error::::UnknownMessageIndex + ); + }); + } } diff --git a/runtime/parachains/src/util.rs b/runtime/parachains/src/util.rs index 4f9d1e588ba1..2e0625f42202 100644 --- a/runtime/parachains/src/util.rs +++ b/runtime/parachains/src/util.rs @@ -18,7 +18,7 @@ //! on all modules. use primitives::v1::{Id as ParaId, PersistedValidationData, ValidatorIndex}; -use sp_std::vec::Vec; +use sp_std::{collections::btree_set::BTreeSet, vec::Vec}; use crate::{configuration, hrmp, paras}; @@ -41,15 +41,53 @@ pub fn make_persisted_validation_data( }) } -/// Take the active subset of a set containing all validators. -pub fn take_active_subset(active_validators: &[ValidatorIndex], set: &[T]) -> Vec { - let subset: Vec<_> = active_validators +/// Take an active subset of a set containing all validators. +/// +/// First item in pair will be all items in set have indices found in the `active` indices set (in +/// the order of the `active` vec, the second item will contain the rest, in the original order. +/// +/// ```ignore +/// split_active_subset(active, all).0 == take_active_subset(active, all) +/// ``` +pub fn split_active_subset(active: &[ValidatorIndex], all: &[T]) -> (Vec, Vec) { + let active_set: BTreeSet<_> = active.iter().cloned().collect(); + // active result has ordering of active set. + let active_result = take_active_subset(active, all); + // inactive result preserves original ordering of `all`. + let inactive_result = all .iter() - .filter_map(|i| set.get(i.0 as usize)) + .enumerate() + .filter(|(i, _)| !active_set.contains(&ValidatorIndex(*i as _))) + .map(|(_, v)| v) .cloned() .collect(); - if subset.len() != active_validators.len() { + if active_result.len() != active.len() { + log::warn!( + target: "runtime::parachains", + "Took active validators from set with wrong size.", + ); + } + + (active_result, inactive_result) +} + +/// Uses `split_active_subset` and concatenates the inactive to the active vec. +/// +/// ```ignore +/// split_active_subset(active, all)[0..active.len()]) == take_active_subset(active, all) +/// ``` +pub fn take_active_subset_and_inactive(active: &[ValidatorIndex], all: &[T]) -> Vec { + let (mut a, mut i) = split_active_subset(active, all); + a.append(&mut i); + a +} + +/// Take the active subset of a set containing all validators. +pub fn take_active_subset(active: &[ValidatorIndex], set: &[T]) -> Vec { + let subset: Vec<_> = active.iter().filter_map(|i| set.get(i.0 as usize)).cloned().collect(); + + if subset.len() != active.len() { log::warn!( target: "runtime::parachains", "Took active validators from set with wrong size", @@ -58,3 +96,23 @@ pub fn take_active_subset(active_validators: &[ValidatorIndex], set: & subset } + +#[cfg(test)] +mod tests { + + use sp_std::vec::Vec; + + use crate::util::{split_active_subset, take_active_subset}; + use primitives::v1::ValidatorIndex; + + #[test] + fn take_active_subset_is_compatible_with_split_active_subset() { + let active: Vec<_> = vec![ValidatorIndex(1), ValidatorIndex(7), ValidatorIndex(3)]; + let validators = vec![9, 1, 6, 7, 4, 5, 2, 3, 0, 8]; + let (selected, unselected) = split_active_subset(&active, &validators); + let selected2 = take_active_subset(&active, &validators); + assert_eq!(selected, selected2); + assert_eq!(unselected, vec![9, 6, 4, 5, 2, 0, 8]); + assert_eq!(selected, vec![1, 3, 7]); + } +} diff --git a/runtime/polkadot/Cargo.toml b/runtime/polkadot/Cargo.toml index c4c8f2d64a72..0a4532100951 100644 --- a/runtime/polkadot/Cargo.toml +++ b/runtime/polkadot/Cargo.toml @@ -8,6 +8,7 @@ build = "build.rs" [dependencies] bitvec = { version = "0.20.1", default-features = false, features = ["alloc"] } parity-scale-codec = { version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } log = { version = "0.4.14", default-features = false } rustc-hex = { version = "2.1.0", default-features = false } serde = { version = "1.0.130", default-features = false } @@ -100,6 +101,7 @@ std = [ "primitives/std", "rustc-hex/std", "parity-scale-codec/std", + "scale-info/std", "inherents/std", "sp-core/std", "sp-api/std", diff --git a/runtime/polkadot/src/lib.rs b/runtime/polkadot/src/lib.rs index 300e37fe8883..2d4e35c630a2 100644 --- a/runtime/polkadot/src/lib.rs +++ b/runtime/polkadot/src/lib.rs @@ -906,7 +906,17 @@ parameter_types! { /// The type used to represent the kinds of proxying allowed. #[derive( - Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, RuntimeDebug, MaxEncodedLen, + Copy, + Clone, + Eq, + PartialEq, + Ord, + PartialOrd, + Encode, + Decode, + RuntimeDebug, + MaxEncodedLen, + scale_info::TypeInfo, )] pub enum ProxyType { Any = 0, @@ -964,9 +974,9 @@ impl InstanceFilter for ProxyType { Call::Scheduler(..) | Call::Babe(..) | Call::Timestamp(..) | - Call::Indices(pallet_indices::Call::claim(..)) | - Call::Indices(pallet_indices::Call::free(..)) | - Call::Indices(pallet_indices::Call::freeze(..)) | + Call::Indices(pallet_indices::Call::claim{..}) | + Call::Indices(pallet_indices::Call::free{..}) | + Call::Indices(pallet_indices::Call::freeze{..}) | // Specifically omitting Indices `transfer`, `force_transfer` // Specifically omitting the entire Balances pallet Call::Authorship(..) | @@ -983,8 +993,8 @@ impl InstanceFilter for ProxyType { Call::Bounties(..) | Call::Tips(..) | Call::Claims(..) | - Call::Vesting(pallet_vesting::Call::vest(..)) | - Call::Vesting(pallet_vesting::Call::vest_other(..)) | + Call::Vesting(pallet_vesting::Call::vest{..}) | + Call::Vesting(pallet_vesting::Call::vest_other{..}) | // Specifically omitting Vesting `vested_transfer`, and `force_vested_transfer` Call::Utility(..) | Call::Identity(..) | @@ -1004,10 +1014,10 @@ impl InstanceFilter for ProxyType { }, ProxyType::IdentityJudgement => matches!( c, - Call::Identity(pallet_identity::Call::provide_judgement(..)) | Call::Utility(..) + Call::Identity(pallet_identity::Call::provide_judgement { .. }) | Call::Utility(..) ), ProxyType::CancelProxy => { - matches!(c, Call::Proxy(pallet_proxy::Call::reject_announcement(..))) + matches!(c, Call::Proxy(pallet_proxy::Call::reject_announcement { .. })) }, } } @@ -1131,11 +1141,66 @@ pub type Executive = frame_executive::Executive< frame_system::ChainContext, Runtime, AllPallets, - (TechnicalMembershipStoragePrefixMigration, MigrateTipsPalletPrefix), + ( + CouncilStoragePrefixMigration, + TechnicalCommitteeStoragePrefixMigration, + TechnicalMembershipStoragePrefixMigration, + MigrateTipsPalletPrefix, + ), >; /// The payload being signed in transactions. pub type SignedPayload = generic::SignedPayload; +const COUNCIL_OLD_PREFIX: &str = "Instance1Collective"; +/// Migrate from `Instance1Collective` to the new pallet prefix `Council` +pub struct CouncilStoragePrefixMigration; + +impl OnRuntimeUpgrade for CouncilStoragePrefixMigration { + fn on_runtime_upgrade() -> frame_support::weights::Weight { + pallet_collective::migrations::v4::migrate::(COUNCIL_OLD_PREFIX) + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result<(), &'static str> { + pallet_collective::migrations::v4::pre_migrate::(COUNCIL_OLD_PREFIX); + Ok(()) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade() -> Result<(), &'static str> { + pallet_collective::migrations::v4::post_migrate::(COUNCIL_OLD_PREFIX); + Ok(()) + } +} + +const TECHNICAL_COMMITTEE_OLD_PREFIX: &str = "Instance2Collective"; +/// Migrate from 'Instance2Collective' to the new pallet prefix `TechnicalCommittee` +pub struct TechnicalCommitteeStoragePrefixMigration; + +impl OnRuntimeUpgrade for TechnicalCommitteeStoragePrefixMigration { + fn on_runtime_upgrade() -> frame_support::weights::Weight { + pallet_collective::migrations::v4::migrate::( + TECHNICAL_COMMITTEE_OLD_PREFIX, + ) + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result<(), &'static str> { + pallet_collective::migrations::v4::pre_migrate::( + TECHNICAL_COMMITTEE_OLD_PREFIX, + ); + Ok(()) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade() -> Result<(), &'static str> { + pallet_collective::migrations::v4::post_migrate::( + TECHNICAL_COMMITTEE_OLD_PREFIX, + ); + Ok(()) + } +} + const TECHNICAL_MEMBERSHIP_OLD_PREFIX: &str = "Instance1Membership"; /// Migrate from `Instance1Membership` to the new pallet prefix `TechnicalMembership` pub struct TechnicalMembershipStoragePrefixMigration; @@ -1216,7 +1281,7 @@ sp_api::impl_runtime_apis! { impl sp_api::Metadata for Runtime { fn metadata() -> OpaqueMetadata { - Runtime::metadata().into() + OpaqueMetadata::new(Runtime::metadata().into()) } } @@ -1644,10 +1709,10 @@ mod test_fees { #[ignore] fn transfer_cost_min_multiplier() { let min_multiplier = runtime_common::MinimumMultiplier::get(); - let call = >::transfer_keep_alive( - Default::default(), - Default::default(), - ); + let call = pallet_balances::Call::::transfer_keep_alive { + dest: Default::default(), + value: Default::default(), + }; let info = call.get_dispatch_info(); // convert to outer call. let call = Call::Balances(call); diff --git a/runtime/rococo/Cargo.toml b/runtime/rococo/Cargo.toml index ed706e19bd34..d3fef706b679 100644 --- a/runtime/rococo/Cargo.toml +++ b/runtime/rococo/Cargo.toml @@ -7,6 +7,7 @@ build = "build.rs" [dependencies] parity-scale-codec = { version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0.130", default-features = false } serde_derive = { version = "1.0.117", optional = true } smallvec = "1.6.1" @@ -92,6 +93,7 @@ std = [ "bp-wococo/std", "bridge-runtime-common/std", "parity-scale-codec/std", + "scale-info/std", "frame-executive/std", "pallet-authority-discovery/std", "pallet-authorship/std", diff --git a/runtime/rococo/src/lib.rs b/runtime/rococo/src/lib.rs index 3da4fba66ec4..cf0a83bfbb41 100644 --- a/runtime/rococo/src/lib.rs +++ b/runtime/rococo/src/lib.rs @@ -46,6 +46,7 @@ use runtime_common::{ BlockHashCount, BlockLength, BlockWeights, RocksDbWeight, SlowAdjustingFeeUpdate, }; use runtime_parachains::{self, runtime_api_impl::v1 as runtime_api_impl}; +use scale_info::TypeInfo; use sp_core::{OpaqueMetadata, RuntimeDebug}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, @@ -718,6 +719,7 @@ impl parachains_ump::Config for Runtime { type Event = Event; type UmpSink = crate::parachains_ump::XcmSink, Runtime>; type FirstMessageFactorPercent = FirstMessageFactorPercent; + type ExecuteOverweightOrigin = EnsureRoot; } impl parachains_dmp::Config for Runtime {} @@ -1033,7 +1035,17 @@ parameter_types! { /// The type used to represent the kinds of proxying allowed. #[derive( - Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, RuntimeDebug, MaxEncodedLen, + Copy, + Clone, + Eq, + PartialEq, + Ord, + PartialOrd, + Encode, + Decode, + RuntimeDebug, + MaxEncodedLen, + TypeInfo, )] pub enum ProxyType { Any, @@ -1050,10 +1062,13 @@ impl InstanceFilter for ProxyType { match self { ProxyType::Any => true, ProxyType::CancelProxy => - matches!(c, Call::Proxy(pallet_proxy::Call::reject_announcement(..))), + matches!(c, Call::Proxy(pallet_proxy::Call::reject_announcement { .. })), ProxyType::Auction => matches!( c, - Call::Auctions(..) | Call::Crowdloan(..) | Call::Registrar(..) | Call::Slots(..) + Call::Auctions { .. } | + Call::Crowdloan { .. } | + Call::Registrar { .. } | + Call::Slots { .. } ), } } @@ -1128,7 +1143,7 @@ sp_api::impl_runtime_apis! { impl sp_api::Metadata for Runtime { fn metadata() -> OpaqueMetadata { - Runtime::metadata().into() + OpaqueMetadata::new(Runtime::metadata().into()) } } diff --git a/runtime/test-runtime/Cargo.toml b/runtime/test-runtime/Cargo.toml index 2072562e7bf5..7a506849efc3 100644 --- a/runtime/test-runtime/Cargo.toml +++ b/runtime/test-runtime/Cargo.toml @@ -10,6 +10,7 @@ bitvec = { version = "0.20.1", default-features = false, features = ["alloc"] } parity-scale-codec = { version = "2.0.0", default-features = false, features = ["derive"] } log = { version = "0.4.14", default-features = false } rustc-hex = { version = "2.1.0", default-features = false } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0.130", default-features = false } serde_derive = { version = "1.0.117", optional = true } smallvec = "1.6.1" @@ -83,6 +84,7 @@ std = [ "primitives/std", "rustc-hex/std", "parity-scale-codec/std", + "scale-info/std", "inherents/std", "sp-core/std", "polkadot-parachain/std", diff --git a/runtime/test-runtime/src/lib.rs b/runtime/test-runtime/src/lib.rs index 723ee4495846..6e2bf146a620 100644 --- a/runtime/test-runtime/src/lib.rs +++ b/runtime/test-runtime/src/lib.rs @@ -491,6 +491,7 @@ impl parachains_ump::Config for Runtime { type Event = Event; type UmpSink = (); type FirstMessageFactorPercent = FirstMessageFactorPercent; + type ExecuteOverweightOrigin = frame_system::EnsureRoot; } parameter_types! { @@ -592,7 +593,8 @@ pub mod pallet_test_notifier { let id = who .using_encoded(|mut d| <[u8; 32]>::decode(&mut d)) .map_err(|_| Error::::BadAccountFormat)?; - let call = Call::::notification_received(0, Default::default()); + let call = + Call::::notification_received { query_id: 0, response: Default::default() }; let qid = pallet_xcm::Pallet::::new_notify_query( Junction::AccountId32 { network: Any, id }.into(), ::Call::from(call), @@ -722,7 +724,7 @@ sp_api::impl_runtime_apis! { impl sp_api::Metadata for Runtime { fn metadata() -> OpaqueMetadata { - Runtime::metadata().into() + OpaqueMetadata::new(Runtime::metadata().into()) } } diff --git a/runtime/westend/Cargo.toml b/runtime/westend/Cargo.toml index d2042126f93f..0568852200d4 100644 --- a/runtime/westend/Cargo.toml +++ b/runtime/westend/Cargo.toml @@ -8,6 +8,7 @@ build = "build.rs" [dependencies] bitvec = { version = "0.20.1", default-features = false, features = ["alloc"] } parity-scale-codec = { version = "2.2.0", default-features = false, features = ["derive", "max-encoded-len"] } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } log = { version = "0.4.14", default-features = false } rustc-hex = { version = "2.1.0", default-features = false } serde = { version = "1.0.130", default-features = false } @@ -105,6 +106,7 @@ std = [ "primitives/std", "rustc-hex/std", "parity-scale-codec/std", + "scale-info/std", "inherents/std", "sp-core/std", "polkadot-parachain/std", diff --git a/runtime/westend/src/lib.rs b/runtime/westend/src/lib.rs index 24e522ef409c..372267d180ab 100644 --- a/runtime/westend/src/lib.rs +++ b/runtime/westend/src/lib.rs @@ -651,7 +651,17 @@ parameter_types! { /// The type used to represent the kinds of proxying allowed. #[derive( - Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, RuntimeDebug, MaxEncodedLen, + Copy, + Clone, + Eq, + PartialEq, + Ord, + PartialOrd, + Encode, + Decode, + RuntimeDebug, + MaxEncodedLen, + scale_info::TypeInfo, )] pub enum ProxyType { Any, @@ -676,9 +686,9 @@ impl InstanceFilter for ProxyType { Call::System(..) | Call::Babe(..) | Call::Timestamp(..) | - Call::Indices(pallet_indices::Call::claim(..)) | - Call::Indices(pallet_indices::Call::free(..)) | - Call::Indices(pallet_indices::Call::freeze(..)) | + Call::Indices(pallet_indices::Call::claim{..}) | + Call::Indices(pallet_indices::Call::free{..}) | + Call::Indices(pallet_indices::Call::freeze{..}) | // Specifically omitting Indices `transfer`, `force_transfer` // Specifically omitting the entire Balances pallet Call::Authorship(..) | @@ -688,24 +698,24 @@ impl InstanceFilter for ProxyType { Call::ImOnline(..) | Call::Utility(..) | Call::Identity(..) | - Call::Recovery(pallet_recovery::Call::as_recovered(..)) | - Call::Recovery(pallet_recovery::Call::vouch_recovery(..)) | - Call::Recovery(pallet_recovery::Call::claim_recovery(..)) | - Call::Recovery(pallet_recovery::Call::close_recovery(..)) | - Call::Recovery(pallet_recovery::Call::remove_recovery(..)) | - Call::Recovery(pallet_recovery::Call::cancel_recovered(..)) | + Call::Recovery(pallet_recovery::Call::as_recovered{..}) | + Call::Recovery(pallet_recovery::Call::vouch_recovery{..}) | + Call::Recovery(pallet_recovery::Call::claim_recovery{..}) | + Call::Recovery(pallet_recovery::Call::close_recovery{..}) | + Call::Recovery(pallet_recovery::Call::remove_recovery{..}) | + Call::Recovery(pallet_recovery::Call::cancel_recovered{..}) | // Specifically omitting Recovery `create_recovery`, `initiate_recovery` - Call::Vesting(pallet_vesting::Call::vest(..)) | - Call::Vesting(pallet_vesting::Call::vest_other(..)) | + Call::Vesting(pallet_vesting::Call::vest{..}) | + Call::Vesting(pallet_vesting::Call::vest_other{..}) | // Specifically omitting Vesting `vested_transfer`, and `force_vested_transfer` Call::Scheduler(..) | // Specifically omitting Sudo pallet Call::Proxy(..) | Call::Multisig(..) | - Call::Registrar(paras_registrar::Call::register(..)) | - Call::Registrar(paras_registrar::Call::deregister(..)) | + Call::Registrar(paras_registrar::Call::register{..}) | + Call::Registrar(paras_registrar::Call::deregister{..}) | // Specifically omitting Registrar `swap` - Call::Registrar(paras_registrar::Call::reserve(..)) | + Call::Registrar(paras_registrar::Call::reserve{..}) | Call::Crowdloan(..) | Call::Slots(..) | Call::Auctions(..) // Specifically omitting the entire XCM Pallet @@ -714,7 +724,7 @@ impl InstanceFilter for ProxyType { matches!(c, Call::Staking(..) | Call::Session(..) | Call::Utility(..)) }, ProxyType::SudoBalances => match c { - Call::Sudo(pallet_sudo::Call::sudo(ref x)) => { + Call::Sudo(pallet_sudo::Call::sudo { call: ref x }) => { matches!(x.as_ref(), &Call::Balances(..)) }, Call::Utility(..) => true, @@ -722,10 +732,10 @@ impl InstanceFilter for ProxyType { }, ProxyType::IdentityJudgement => matches!( c, - Call::Identity(pallet_identity::Call::provide_judgement(..)) | Call::Utility(..) + Call::Identity(pallet_identity::Call::provide_judgement { .. }) | Call::Utility(..) ), ProxyType::CancelProxy => { - matches!(c, Call::Proxy(pallet_proxy::Call::reject_announcement(..))) + matches!(c, Call::Proxy(pallet_proxy::Call::reject_announcement { .. })) }, ProxyType::Auction => matches!( c, @@ -786,6 +796,7 @@ impl parachains_ump::Config for Runtime { type Event = Event; type UmpSink = crate::parachains_ump::XcmSink, Runtime>; type FirstMessageFactorPercent = FirstMessageFactorPercent; + type ExecuteOverweightOrigin = EnsureRoot; } impl parachains_dmp::Config for Runtime {} @@ -1108,7 +1119,7 @@ sp_api::impl_runtime_apis! { impl sp_api::Metadata for Runtime { fn metadata() -> OpaqueMetadata { - Runtime::metadata().into() + OpaqueMetadata::new(Runtime::metadata().into()) } } diff --git a/scripts/gitlab/lingua.dic b/scripts/gitlab/lingua.dic index 969bdc22986d..3085fbc3c32c 100644 --- a/scripts/gitlab/lingua.dic +++ b/scripts/gitlab/lingua.dic @@ -253,6 +253,7 @@ timestamp/MS transitionary trie/MS trustless/Y +TTL tuple/SM typesystem ubuntu/M @@ -296,6 +297,7 @@ WND/S Wococo XCM/S XCMP/M +yeet decrement DM -ParaId \ No newline at end of file +ParaId diff --git a/utils/staking-miner/src/main.rs b/utils/staking-miner/src/main.rs index 45140323807f..59c8846db28c 100644 --- a/utils/staking-miner/src/main.rs +++ b/utils/staking-miner/src/main.rs @@ -81,7 +81,7 @@ macro_rules! construct_runtime_prelude { let crate::signer::Signer { account, pair, .. } = signer; - let local_call = EPMCall::::submit(Box::new(raw_solution), witness); + let local_call = EPMCall::::submit { raw_solution: Box::new(raw_solution), num_signed_submissions: witness }; let call: Call = as std::convert::TryInto>::try_into(local_call) .expect("election provider pallet must exist in the runtime, thus \ inner call can be converted, qed." diff --git a/xcm/Cargo.toml b/xcm/Cargo.toml index 12b96a502165..21becd6cb140 100644 --- a/xcm/Cargo.toml +++ b/xcm/Cargo.toml @@ -8,6 +8,7 @@ edition = "2018" [dependencies] impl-trait-for-tuples = "0.2.0" parity-scale-codec = { version = "2.0.0", default-features = false, features = [ "derive" ] } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } derivative = {version = "2.2.0", default-features = false, features = [ "use_core" ] } log = { version = "0.4.14", default-features = false } xcm-procedural = { path = "procedural" } @@ -17,4 +18,5 @@ default = ["std"] wasm-api = [] std = [ "parity-scale-codec/std", + "scale-info/std", ] diff --git a/xcm/pallet-xcm/Cargo.toml b/xcm/pallet-xcm/Cargo.toml index e8c586ae4908..96c6e3d42a31 100644 --- a/xcm/pallet-xcm/Cargo.toml +++ b/xcm/pallet-xcm/Cargo.toml @@ -6,6 +6,7 @@ version = "0.9.9" [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0.130", optional = true, features = ["derive"] } log = { version = "0.4.14", default-features = false } @@ -29,6 +30,7 @@ polkadot-parachain = { path = "../../parachain" } default = ["std"] std = [ "codec/std", + "scale-info/std", "serde", "sp-std/std", "sp-core/std", diff --git a/xcm/pallet-xcm/src/lib.rs b/xcm/pallet-xcm/src/lib.rs index 314a929803cd..972e3f926829 100644 --- a/xcm/pallet-xcm/src/lib.rs +++ b/xcm/pallet-xcm/src/lib.rs @@ -25,6 +25,7 @@ mod tests; use codec::{Decode, Encode, EncodeLike}; use frame_support::traits::{Contains, EnsureOrigin, Get, OriginTrait}; +use scale_info::TypeInfo; use sp_runtime::{ traits::{BadOrigin, Saturating}, RuntimeDebug, @@ -217,7 +218,7 @@ pub mod pallet { } #[pallet::origin] - #[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)] + #[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo)] pub enum Origin { /// It comes from somewhere in the XCM space wanting to transact. Xcm(MultiLocation), @@ -264,7 +265,7 @@ pub mod pallet { } /// The status of a query. - #[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug)] + #[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] pub enum QueryStatus { /// The query was sent but no response has yet been received. Pending { @@ -290,7 +291,7 @@ pub mod pallet { } } - #[derive(Clone, Encode, Decode, Eq, PartialEq, Ord, PartialOrd)] + #[derive(Clone, Encode, Decode, Eq, PartialEq, Ord, PartialOrd, TypeInfo)] pub enum VersionMigrationStage { MigrateSupportedVersion, MigrateVersionNotifiers, diff --git a/xcm/pallet-xcm/src/mock.rs b/xcm/pallet-xcm/src/mock.rs index c841d896acab..d6ccbd4abfc9 100644 --- a/xcm/pallet-xcm/src/mock.rs +++ b/xcm/pallet-xcm/src/mock.rs @@ -93,7 +93,8 @@ pub mod pallet_test_notifier { let id = who .using_encoded(|mut d| <[u8; 32]>::decode(&mut d)) .map_err(|_| Error::::BadAccountFormat)?; - let call = Call::::notification_received(0, Default::default()); + let call = + Call::::notification_received { query_id: 0, response: Default::default() }; let qid = crate::Pallet::::new_notify_query( Junction::AccountId32 { network: Any, id }.into(), ::Call::from(call), diff --git a/xcm/pallet-xcm/src/tests.rs b/xcm/pallet-xcm/src/tests.rs index 56f3579cc1e7..82e6c524f269 100644 --- a/xcm/pallet-xcm/src/tests.rs +++ b/xcm/pallet-xcm/src/tests.rs @@ -44,7 +44,10 @@ fn report_outcome_notify_works() { assets: (Here, SEND_AMOUNT).into(), beneficiary: sender.clone(), }]); - let call = pallet_test_notifier::Call::notification_received(0, Default::default()); + let call = pallet_test_notifier::Call::notification_received { + query_id: 0, + response: Default::default(), + }; let notify = Call::TestNotifier(call); new_test_ext_with_balances(balances).execute_with(|| { XcmPallet::report_outcome_notify(&mut message, Parachain(PARA_ID).into(), notify, 100) diff --git a/xcm/src/double_encoded.rs b/xcm/src/double_encoded.rs index ae21336d13c3..858d97964203 100644 --- a/xcm/src/double_encoded.rs +++ b/xcm/src/double_encoded.rs @@ -20,9 +20,10 @@ use parity_scale_codec::{Decode, DecodeLimit, Encode}; /// Wrapper around the encoded and decoded versions of a value. /// Caches the decoded value once computed. -#[derive(Encode, Decode)] +#[derive(Encode, Decode, scale_info::TypeInfo)] #[codec(encode_bound())] #[codec(decode_bound())] +#[scale_info(bounds(), skip_type_params(T))] pub struct DoubleEncoded { encoded: Vec, #[codec(skip)] diff --git a/xcm/src/lib.rs b/xcm/src/lib.rs index ff5f0cd4eba2..87aad30c79f4 100644 --- a/xcm/src/lib.rs +++ b/xcm/src/lib.rs @@ -30,6 +30,7 @@ use core::{ }; use derivative::Derivative; use parity_scale_codec::{Decode, Encode, Error as CodecError, Input}; +use scale_info::TypeInfo; pub mod v0; pub mod v1; @@ -69,7 +70,7 @@ pub trait IntoVersion: Sized { } /// A single `MultiLocation` value, together with its version code. -#[derive(Derivative, Encode, Decode)] +#[derive(Derivative, Encode, Decode, TypeInfo)] #[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))] #[codec(encode_bound())] #[codec(decode_bound())] @@ -123,7 +124,7 @@ impl TryFrom for v1::MultiLocation { } /// A single `Response` value, together with its version code. -#[derive(Derivative, Encode, Decode)] +#[derive(Derivative, Encode, Decode, TypeInfo)] #[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))] #[codec(encode_bound())] #[codec(decode_bound())] @@ -199,7 +200,7 @@ impl TryFrom for v2::Response { } /// A single `MultiAsset` value, together with its version code. -#[derive(Derivative, Encode, Decode)] +#[derive(Derivative, Encode, Decode, TypeInfo)] #[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))] #[codec(encode_bound())] #[codec(decode_bound())] @@ -253,7 +254,7 @@ impl TryFrom for v1::MultiAsset { } /// A single `MultiAssets` value, together with its version code. -#[derive(Derivative, Encode, Decode)] +#[derive(Derivative, Encode, Decode, TypeInfo)] #[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))] #[codec(encode_bound())] #[codec(decode_bound())] @@ -307,10 +308,11 @@ impl TryFrom for v1::MultiAssets { } /// A single XCM message, together with its version code. -#[derive(Derivative, Encode, Decode)] +#[derive(Derivative, Encode, Decode, TypeInfo)] #[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))] #[codec(encode_bound())] #[codec(decode_bound())] +#[scale_info(bounds(), skip_type_params(Call))] pub enum VersionedXcm { V0(v0::Xcm), V1(v1::Xcm), diff --git a/xcm/src/v0/junction.rs b/xcm/src/v0/junction.rs index 171327a5f28a..0c559ca5a136 100644 --- a/xcm/src/v0/junction.rs +++ b/xcm/src/v0/junction.rs @@ -18,9 +18,10 @@ use alloc::vec::Vec; use parity_scale_codec::{Decode, Encode}; +use scale_info::TypeInfo; /// A global identifier of an account-bearing consensus system. -#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug)] +#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, TypeInfo)] pub enum NetworkId { /// Unidentified/any. Any, @@ -33,7 +34,7 @@ pub enum NetworkId { } /// An identifier of a pluralistic body. -#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug)] +#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, TypeInfo)] pub enum BodyId { /// The only body in its context. Unit, @@ -54,7 +55,7 @@ pub enum BodyId { } /// A part of a pluralistic body. -#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug)] +#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, TypeInfo)] pub enum BodyPart { /// The body's declaration, under whatever means it decides. Voice, @@ -101,7 +102,7 @@ impl BodyPart { /// A single item in a path to describe the relative location of a consensus system. /// /// Each item assumes a pre-existing location as its context and is defined in terms of it. -#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug)] +#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, TypeInfo)] pub enum Junction { /// The consensus system of which the context is a member and state-wise super-set. /// diff --git a/xcm/src/v0/mod.rs b/xcm/src/v0/mod.rs index 9ec5150242be..35889d8daab2 100644 --- a/xcm/src/v0/mod.rs +++ b/xcm/src/v0/mod.rs @@ -24,6 +24,7 @@ use core::{ }; use derivative::Derivative; use parity_scale_codec::{self, Decode, Encode}; +use scale_info::TypeInfo; mod junction; mod multi_asset; @@ -58,7 +59,7 @@ pub mod prelude { // the number of items in the vector. /// Basically just the XCM (more general) version of `ParachainDispatchOrigin`. -#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, Debug)] +#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo)] 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 @@ -81,7 +82,7 @@ pub enum OriginKind { } /// Response data to a query. -#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug)] +#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo)] pub enum Response { /// Some assets. Assets(Vec), @@ -95,10 +96,11 @@ pub enum Response { /// /// This is the inner XCM format and is version-sensitive. Messages are typically passed using the outer /// XCM format, known as `VersionedXcm`. -#[derive(Derivative, Encode, Decode)] +#[derive(Derivative, Encode, Decode, TypeInfo)] #[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))] #[codec(encode_bound())] #[codec(decode_bound())] +#[scale_info(bounds(), skip_type_params(Call))] pub enum Xcm { /// Withdraw asset(s) (`assets`) from the ownership of `origin` and place them into `holding`. Execute the /// orders (`effects`). diff --git a/xcm/src/v0/multi_asset.rs b/xcm/src/v0/multi_asset.rs index ee541c3c681f..dac5a6bfeb7e 100644 --- a/xcm/src/v0/multi_asset.rs +++ b/xcm/src/v0/multi_asset.rs @@ -24,6 +24,7 @@ use core::{ result, }; use parity_scale_codec::{self, Decode, Encode}; +use scale_info::TypeInfo; pub use crate::v1::AssetInstance; @@ -82,7 +83,7 @@ pub use crate::v1::AssetInstance; /// - `/AccountId32` for an ERC-20-style single-asset smart-contract on a Frame-based contracts chain. /// - `/AccountKey20` for an ERC-20-style single-asset smart-contract on an Ethereum-like chain. /// -#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug)] +#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, TypeInfo)] pub enum MultiAsset { /// No assets. Rarely used. None, diff --git a/xcm/src/v0/multi_location.rs b/xcm/src/v0/multi_location.rs index 6205071690f0..6b7438b93fa0 100644 --- a/xcm/src/v0/multi_location.rs +++ b/xcm/src/v0/multi_location.rs @@ -42,7 +42,7 @@ use parity_scale_codec::{self, Decode, Encode}; /// This specific `MultiLocation` implementation uses a Rust `enum` in order to make pattern matching easier. /// /// The `MultiLocation` value of `Null` simply refers to the interpreting consensus system. -#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug)] +#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, scale_info::TypeInfo)] pub enum MultiLocation { /// The interpreting consensus system. Null, diff --git a/xcm/src/v0/order.rs b/xcm/src/v0/order.rs index e414cc27a6e2..54117e31f9c5 100644 --- a/xcm/src/v0/order.rs +++ b/xcm/src/v0/order.rs @@ -26,10 +26,11 @@ use derivative::Derivative; use parity_scale_codec::{self, Decode, Encode}; /// An instruction to be executed on some or all of the assets in holding, used by asset-related XCM messages. -#[derive(Derivative, Encode, Decode)] +#[derive(Derivative, Encode, Decode, scale_info::TypeInfo)] #[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))] #[codec(encode_bound())] #[codec(decode_bound())] +#[scale_info(bounds(), skip_type_params(Call))] pub enum Order { /// Do nothing. Not generally used. #[codec(index = 0)] diff --git a/xcm/src/v0/traits.rs b/xcm/src/v0/traits.rs index 5c9882f61dbb..3263fda4ac56 100644 --- a/xcm/src/v0/traits.rs +++ b/xcm/src/v0/traits.rs @@ -21,7 +21,7 @@ use parity_scale_codec::{Decode, Encode}; use super::{MultiLocation, Xcm}; -#[derive(Clone, Encode, Decode, Eq, PartialEq, Debug)] +#[derive(Clone, Encode, Decode, Eq, PartialEq, Debug, scale_info::TypeInfo)] pub enum Error { Undefined, /// An arithmetic overflow happened. @@ -103,7 +103,7 @@ pub type Result = result::Result<(), Error>; pub type Weight = u64; /// Outcome of an XCM execution. -#[derive(Clone, Encode, Decode, Eq, PartialEq, Debug)] +#[derive(Clone, Encode, Decode, Eq, PartialEq, Debug, scale_info::TypeInfo)] pub enum Outcome { /// Execution completed successfully; given weight was used. Complete(Weight), diff --git a/xcm/src/v1/junction.rs b/xcm/src/v1/junction.rs index 06e7308ad411..c4835d60c5b1 100644 --- a/xcm/src/v1/junction.rs +++ b/xcm/src/v1/junction.rs @@ -21,11 +21,12 @@ use crate::v0::Junction as Junction0; use alloc::vec::Vec; use core::convert::TryFrom; use parity_scale_codec::{self, Decode, Encode}; +use scale_info::TypeInfo; /// A single item in a path to describe the relative location of a consensus system. /// /// Each item assumes a pre-existing location as its context and is defined in terms of it. -#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug)] +#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, TypeInfo)] pub enum Junction { /// An indexed parachain belonging to and operated by the context. /// diff --git a/xcm/src/v1/mod.rs b/xcm/src/v1/mod.rs index 02bbd5f42712..6f96dc739491 100644 --- a/xcm/src/v1/mod.rs +++ b/xcm/src/v1/mod.rs @@ -29,6 +29,7 @@ use core::{ }; use derivative::Derivative; use parity_scale_codec::{self, Decode, Encode}; +use scale_info::TypeInfo; mod junction; mod multiasset; @@ -75,7 +76,7 @@ pub mod prelude { } /// Response data to a query. -#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug)] +#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo)] pub enum Response { /// Some assets. Assets(MultiAssets), @@ -91,10 +92,11 @@ pub enum Response { /// /// This is the inner XCM format and is version-sensitive. Messages are typically passed using the outer /// XCM format, known as `VersionedXcm`. -#[derive(Derivative, Encode, Decode)] +#[derive(Derivative, Encode, Decode, TypeInfo)] #[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))] #[codec(encode_bound())] #[codec(decode_bound())] +#[scale_info(bounds(), skip_type_params(Call))] pub enum Xcm { /// Withdraw asset(s) (`assets`) from the ownership of `origin` and place them into `holding`. Execute the /// orders (`effects`). diff --git a/xcm/src/v1/multiasset.rs b/xcm/src/v1/multiasset.rs index a5dfdc84968c..129c5731542f 100644 --- a/xcm/src/v1/multiasset.rs +++ b/xcm/src/v1/multiasset.rs @@ -31,9 +31,10 @@ use core::{ result, }; use parity_scale_codec::{self as codec, Decode, Encode}; +use scale_info::TypeInfo; /// A general identifier for an instance of a non-fungible asset class. -#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug)] +#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, TypeInfo)] pub enum AssetInstance { /// Undefined - used if the non-fungible asset class has only one instance. Undefined, @@ -95,7 +96,7 @@ impl From> for AssetInstance { } /// Classification of an asset being concrete or abstract. -#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Encode, Decode)] +#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Encode, Decode, TypeInfo)] pub enum AssetId { Concrete(MultiLocation), Abstract(Vec), @@ -135,7 +136,7 @@ impl AssetId { } /// Classification of whether an asset is fungible or not, along with a mandatory amount or instance. -#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Encode, Decode)] +#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Encode, Decode, TypeInfo)] pub enum Fungibility { Fungible(#[codec(compact)] u128), NonFungible(AssetInstance), @@ -162,7 +163,7 @@ impl> From for Fungibility { } } -#[derive(Clone, Eq, PartialEq, Debug, Encode, Decode)] +#[derive(Clone, Eq, PartialEq, Debug, Encode, Decode, TypeInfo)] pub struct MultiAsset { pub id: AssetId, pub fun: Fungibility, @@ -266,7 +267,7 @@ impl TryFrom> for MultiAsset { } /// A `Vec` of `MultiAsset`s. There may be no duplicate fungible items in here and when decoding, they must be sorted. -#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Encode)] +#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Encode, TypeInfo)] pub struct MultiAssets(Vec); impl Decode for MultiAssets { @@ -422,14 +423,14 @@ impl MultiAssets { } } /// Classification of whether an asset is fungible or not. -#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Encode, Decode)] +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Encode, Decode, TypeInfo)] pub enum WildFungibility { Fungible, NonFungible, } /// A wildcard representing a set of assets. -#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Encode, Decode)] +#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Encode, Decode, TypeInfo)] pub enum WildMultiAsset { /// All assets in the holding register, up to `usize` individual assets (different instances of non-fungibles could /// be separate assets). @@ -501,7 +502,7 @@ impl, B: Into> From<(A, B)> for WildMultiAsset /// /// Note: Vectors of wildcards whose encoding is supported in XCM v0 are unsupported /// in this implementation and will result in a decode error. -#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Encode, Decode)] +#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Encode, Decode, TypeInfo)] pub enum MultiAssetFilter { Definite(MultiAssets), Wild(WildMultiAsset), diff --git a/xcm/src/v1/multilocation.rs b/xcm/src/v1/multilocation.rs index a2a087443b3c..9c472553a37c 100644 --- a/xcm/src/v1/multilocation.rs +++ b/xcm/src/v1/multilocation.rs @@ -19,6 +19,7 @@ use super::Junction; use core::{convert::TryFrom, mem, result}; use parity_scale_codec::{Decode, Encode}; +use scale_info::TypeInfo; /// A relative path between state-bearing consensus systems. /// @@ -46,7 +47,7 @@ use parity_scale_codec::{Decode, Encode}; /// that a value is strictly an interior location, in those cases, `Junctions` may be used. /// /// The `MultiLocation` value of `Null` simply refers to the interpreting consensus system. -#[derive(Clone, Decode, Encode, Eq, PartialEq, Ord, PartialOrd, Debug)] +#[derive(Clone, Decode, Encode, Eq, PartialEq, Ord, PartialOrd, Debug, TypeInfo)] pub struct MultiLocation { /// The number of parent junctions at the beginning of this `MultiLocation`. pub parents: u8, @@ -370,7 +371,7 @@ const MAX_JUNCTIONS: usize = 8; /// /// Parent junctions cannot be constructed with this type. Refer to `MultiLocation` for /// instructions on constructing parent junctions. -#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug)] +#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, TypeInfo)] pub enum Junctions { /// The interpreting consensus system. Here, diff --git a/xcm/src/v1/order.rs b/xcm/src/v1/order.rs index 9b8a7591f183..00ee69458cd0 100644 --- a/xcm/src/v1/order.rs +++ b/xcm/src/v1/order.rs @@ -25,12 +25,14 @@ use core::{ }; use derivative::Derivative; use parity_scale_codec::{self, Decode, Encode}; +use scale_info::TypeInfo; /// An instruction to be executed on some or all of the assets in holding, used by asset-related XCM messages. -#[derive(Derivative, Encode, Decode)] +#[derive(Derivative, Encode, Decode, TypeInfo)] #[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))] #[codec(encode_bound())] #[codec(decode_bound())] +#[scale_info(bounds(), skip_type_params(Call))] pub enum Order { /// Do nothing. Not generally used. #[codec(index = 0)] diff --git a/xcm/src/v1/traits.rs b/xcm/src/v1/traits.rs index 892b6afea9f7..445ab25d4c7f 100644 --- a/xcm/src/v1/traits.rs +++ b/xcm/src/v1/traits.rs @@ -18,10 +18,11 @@ use core::result; use parity_scale_codec::{Decode, Encode}; +use scale_info::TypeInfo; use super::{MultiLocation, Xcm}; -#[derive(Clone, Encode, Decode, Eq, PartialEq, Debug)] +#[derive(Clone, Encode, Decode, Eq, PartialEq, Debug, TypeInfo)] pub enum Error { Undefined, /// An arithmetic overflow happened. @@ -105,7 +106,7 @@ pub type Result = result::Result<(), Error>; pub type Weight = u64; /// Outcome of an XCM execution. -#[derive(Clone, Encode, Decode, Eq, PartialEq, Debug)] +#[derive(Clone, Encode, Decode, Eq, PartialEq, Debug, TypeInfo)] pub enum Outcome { /// Execution completed successfully; given weight was used. Complete(Weight), diff --git a/xcm/src/v2/mod.rs b/xcm/src/v2/mod.rs index 943582ceca8b..2456884e7972 100644 --- a/xcm/src/v2/mod.rs +++ b/xcm/src/v2/mod.rs @@ -26,6 +26,7 @@ use core::{ }; use derivative::Derivative; use parity_scale_codec::{self, Decode, Encode}; +use scale_info::TypeInfo; mod traits; @@ -45,10 +46,11 @@ pub const VERSION: super::Version = 2; /// An identifier for a query. pub type QueryId = u64; -#[derive(Derivative, Default, Encode, Decode)] +#[derive(Derivative, Default, Encode, Decode, TypeInfo)] #[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))] #[codec(encode_bound())] #[codec(decode_bound())] +#[scale_info(bounds(), skip_type_params(Call))] pub struct Xcm(pub Vec>); impl Xcm { @@ -143,7 +145,7 @@ pub mod prelude { } /// Response data to a query. -#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug)] +#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo)] pub enum Response { /// No response. Serves as a neutral default. Null, @@ -162,7 +164,7 @@ impl Default for Response { } /// An optional weight limit. -#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug)] +#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo)] pub enum WeightLimit { /// No weight limit imposed. Unlimited, @@ -196,10 +198,11 @@ impl From for Option { /// /// This is the inner XCM format and is version-sensitive. Messages are typically passed using the outer /// XCM format, known as `VersionedXcm`. -#[derive(Derivative, Encode, Decode)] +#[derive(Derivative, Encode, Decode, TypeInfo)] #[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))] #[codec(encode_bound())] #[codec(decode_bound())] +#[scale_info(bounds(), skip_type_params(Call))] pub enum Instruction { /// Withdraw asset(s) (`assets`) from the ownership of `origin` and place them into the Holding /// Register. diff --git a/xcm/src/v2/traits.rs b/xcm/src/v2/traits.rs index e020fd046e82..a28137b00052 100644 --- a/xcm/src/v2/traits.rs +++ b/xcm/src/v2/traits.rs @@ -18,10 +18,11 @@ use core::result; use parity_scale_codec::{Decode, Encode}; +use scale_info::TypeInfo; use super::*; -#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, Debug)] +#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, Debug, TypeInfo)] pub enum Error { Undefined, /// An arithmetic overflow happened. @@ -126,7 +127,7 @@ pub type Result = result::Result<(), Error>; pub type Weight = u64; /// Outcome of an XCM execution. -#[derive(Clone, Encode, Decode, Eq, PartialEq, Debug)] +#[derive(Clone, Encode, Decode, Eq, PartialEq, Debug, TypeInfo)] pub enum Outcome { /// Execution completed successfully; given weight was used. Complete(Weight), @@ -201,7 +202,7 @@ impl ExecuteXcm for () { } /// Error result value when attempting to send an XCM message. -#[derive(Clone, Encode, Decode, Eq, PartialEq, Debug)] +#[derive(Clone, Encode, Decode, Eq, PartialEq, Debug, scale_info::TypeInfo)] pub enum SendError { /// The message and destination combination was not recognized as being reachable. /// diff --git a/xcm/xcm-builder/Cargo.toml b/xcm/xcm-builder/Cargo.toml index d7119b34d531..b482c5799a4f 100644 --- a/xcm/xcm-builder/Cargo.toml +++ b/xcm/xcm-builder/Cargo.toml @@ -7,6 +7,7 @@ version = "0.9.9" [dependencies] parity-scale-codec = { version = "2.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } xcm = { path = "..", default-features = false } xcm-executor = { path = "../xcm-executor", default-features = false } sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -32,6 +33,7 @@ runtime-benchmarks = [] std = [ "log/std", "parity-scale-codec/std", + "scale-info/std", "xcm/std", "xcm-executor/std", "sp-std/std", diff --git a/xcm/xcm-builder/src/mock.rs b/xcm/xcm-builder/src/mock.rs index 8f6759582f9a..67a2cd8c9aec 100644 --- a/xcm/xcm-builder/src/mock.rs +++ b/xcm/xcm-builder/src/mock.rs @@ -53,7 +53,7 @@ pub enum TestOrigin { /// /// Each item contains the amount of weight that it *wants* to consume as the first item, and the actual amount (if /// different from the former) in the second option. -#[derive(Debug, Encode, Decode, Eq, PartialEq, Clone, Copy)] +#[derive(Debug, Encode, Decode, Eq, PartialEq, Clone, Copy, scale_info::TypeInfo)] pub enum TestCall { OnlyRoot(Weight, Option), OnlyParachain(Weight, Option, Option), diff --git a/xcm/xcm-executor/integration-tests/src/lib.rs b/xcm/xcm-executor/integration-tests/src/lib.rs index 72aa7b15d07b..359a5ef7a39e 100644 --- a/xcm/xcm-executor/integration-tests/src/lib.rs +++ b/xcm/xcm-executor/integration-tests/src/lib.rs @@ -44,10 +44,10 @@ fn basic_buy_fees_message_executes() { let execute = construct_extrinsic( &client, - polkadot_test_runtime::Call::Xcm(pallet_xcm::Call::execute( - Box::new(VersionedXcm::from(msg)), - 1_000_000_000, - )), + polkadot_test_runtime::Call::Xcm(pallet_xcm::Call::execute { + message: Box::new(VersionedXcm::from(msg)), + max_weight: 1_000_000_000, + }), sp_keyring::Sr25519Keyring::Alice, 0, ); @@ -88,7 +88,7 @@ fn query_response_fires() { let execute = construct_extrinsic( &client, - polkadot_test_runtime::Call::TestNotifier(pallet_test_notifier::Call::prepare_new_query()), + polkadot_test_runtime::Call::TestNotifier(pallet_test_notifier::Call::prepare_new_query {}), sp_keyring::Sr25519Keyring::Alice, 0, ); @@ -124,7 +124,10 @@ fn query_response_fires() { let execute = construct_extrinsic( &client, - polkadot_test_runtime::Call::Xcm(pallet_xcm::Call::execute(msg, 1_000_000_000)), + polkadot_test_runtime::Call::Xcm(pallet_xcm::Call::execute { + message: msg, + max_weight: 1_000_000_000, + }), sp_keyring::Sr25519Keyring::Alice, 1, ); @@ -173,7 +176,7 @@ fn query_response_elicits_handler() { let execute = construct_extrinsic( &client, polkadot_test_runtime::Call::TestNotifier( - pallet_test_notifier::Call::prepare_new_notify_query(), + pallet_test_notifier::Call::prepare_new_notify_query {}, ), sp_keyring::Sr25519Keyring::Alice, 0, @@ -209,10 +212,10 @@ fn query_response_elicits_handler() { let execute = construct_extrinsic( &client, - polkadot_test_runtime::Call::Xcm(pallet_xcm::Call::execute( - Box::new(VersionedXcm::from(msg)), - 1_000_000_000, - )), + polkadot_test_runtime::Call::Xcm(pallet_xcm::Call::execute { + message: Box::new(VersionedXcm::from(msg)), + max_weight: 1_000_000_000, + }), sp_keyring::Sr25519Keyring::Alice, 1, ); diff --git a/xcm/xcm-simulator/example/Cargo.toml b/xcm/xcm-simulator/example/Cargo.toml index 5a8f1ac0b867..b4a8cc93e537 100644 --- a/xcm/xcm-simulator/example/Cargo.toml +++ b/xcm/xcm-simulator/example/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0" } +scale-info = { version = "1.0", features = ["derive"] } frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/xcm/xcm-simulator/example/src/lib.rs b/xcm/xcm-simulator/example/src/lib.rs index e93393e54d7f..1f6d2934a673 100644 --- a/xcm/xcm-simulator/example/src/lib.rs +++ b/xcm/xcm-simulator/example/src/lib.rs @@ -118,9 +118,10 @@ mod tests { fn dmp() { MockNet::reset(); - let remark = parachain::Call::System( - frame_system::Call::::remark_with_event(vec![1, 2, 3]), - ); + let remark = + parachain::Call::System(frame_system::Call::::remark_with_event { + remark: vec![1, 2, 3], + }); Relay::execute_with(|| { assert_ok!(RelayChainPalletXcm::send_xcm( Here, @@ -146,7 +147,7 @@ mod tests { MockNet::reset(); let remark = relay_chain::Call::System( - frame_system::Call::::remark_with_event(vec![1, 2, 3]), + frame_system::Call::::remark_with_event { remark: vec![1, 2, 3] }, ); ParaA::execute_with(|| { assert_ok!(ParachainPalletXcm::send_xcm( @@ -172,9 +173,10 @@ mod tests { fn xcmp() { MockNet::reset(); - let remark = parachain::Call::System( - frame_system::Call::::remark_with_event(vec![1, 2, 3]), - ); + let remark = + parachain::Call::System(frame_system::Call::::remark_with_event { + remark: vec![1, 2, 3], + }); ParaA::execute_with(|| { assert_ok!(ParachainPalletXcm::send_xcm( Here, diff --git a/xcm/xcm-simulator/example/src/relay_chain.rs b/xcm/xcm-simulator/example/src/relay_chain.rs index 3b27d800a510..a6f6f1989174 100644 --- a/xcm/xcm-simulator/example/src/relay_chain.rs +++ b/xcm/xcm-simulator/example/src/relay_chain.rs @@ -166,6 +166,7 @@ impl ump::Config for Runtime { type Event = Event; type UmpSink = ump::XcmSink, Runtime>; type FirstMessageFactorPercent = FirstMessageFactorPercent; + type ExecuteOverweightOrigin = frame_system::EnsureRoot; } impl origin::Config for Runtime {}