referrerpolicy=no-referrer-when-downgrade

registrar_primitives/
lib.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! # Parachain-registrar shared primitives
19//!
20//! Types shared by the parachain registrar pallet (`pallet-registrar-para`) and relay-chain
21//! registrar pallet (`pallet-registrar-relay`). This crate is deliberately free of any FRAME,
22//! XCM, or network-specific dependency, so a single version of the wire types serves Westend,
23//! Kusama and Polkadot, and so both pallets can depend on it without forming a dependency cycle.
24//!
25//! For the same reason the types here are plain: a para id is a `u32` (byte-compatible with the
26//! relay chain's `Id` newtype), head data and validation code are `Vec<u8>`, and a validation
27//! code hash is an [`H256`] (what `ValidationCodeHash` wraps). The same holds for
28//! [`ParachainRegistrar`], the interface the relay pallet drives the registry through: conversion
29//! to the relay chain's own types happens in the pallet implementing it.
30
31#![cfg_attr(not(feature = "std"), no_std)]
32
33extern crate alloc;
34
35use alloc::vec::Vec;
36use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
37use scale_info::TypeInfo;
38use sp_core::H256;
39
40/// A parachain id.
41///
42/// Byte-compatible with the relay chain's `Id`, which is a transparent `u32` newtype.
43pub type ParaId = u32;
44
45/// Registrar control-plane messages sent to the relay chain.
46///
47/// The variant's `#[codec(index)]` is the on-wire version tag.
48#[derive(Encode, Decode, DecodeWithMemTracking, Clone, Eq, PartialEq, Debug, TypeInfo)]
49pub enum MessageToRelay<AccountId> {
50	/// Version 1 of the registrar control-plane messages to the relay chain.
51	#[codec(index = 0)]
52	V1(MessageToRelayV1<AccountId>),
53}
54
55/// Version 1 payloads for [`MessageToRelay`].
56#[derive(Encode, Decode, DecodeWithMemTracking, Clone, Eq, PartialEq, Debug, TypeInfo)]
57pub enum MessageToRelayV1<AccountId> {
58	/// Ask the relay chain to accept a registration for `para_id`.
59	///
60	/// The deposit for this registration is already held on the parachain; the relay chain takes
61	/// nothing. The validation code itself is not included: only its hash and length are, and the
62	/// blob is uploaded to the relay chain separately.
63	#[codec(index = 0)]
64	Register {
65		/// The para id being registered. Already reserved on the parachain.
66		para_id: ParaId,
67		/// The parachain's id for this message, echoed back in the response.
68		message_id: u64,
69		/// The account that manages this registration and holds the deposit on the parachain.
70		manager: AccountId,
71		/// The genesis head data of the new parachain.
72		genesis_head: Vec<u8>,
73		/// Blake2-256 hash of the validation code that will be uploaded.
74		code_hash: H256,
75		/// Length of the validation code that will be uploaded, in bytes.
76		///
77		/// The deposit on the parachain was computed from this, so the relay chain must reject any
78		/// blob whose length differs.
79		code_len: u32,
80	},
81	/// Ask the relay chain to drop the authorization it is holding for `para_id`.
82	///
83	/// Sent when the manager gives up on a registration whose validation code never arrived. The
84	/// relay chain never abandons an authorization by itself, so this is what ends a registration
85	/// that is going nowhere, and the manager pays for it. Answered with
86	/// [`MessageToParaV1::CancelResponse`].
87	#[codec(index = 1)]
88	CancelRegistration {
89		/// The para id whose authorization should be dropped.
90		para_id: ParaId,
91		/// The parachain's id for this message, echoed back in the response.
92		message_id: u64,
93	},
94}
95
96/// Registrar report messages sent back to the parachain.
97///
98/// The variant's `#[codec(index)]` is the on-wire version tag.
99#[derive(
100	Encode, Decode, DecodeWithMemTracking, Clone, Eq, PartialEq, Debug, TypeInfo, MaxEncodedLen,
101)]
102pub enum MessageToPara {
103	/// Version 1 of the registrar report messages to the parachain.
104	#[codec(index = 0)]
105	V1(MessageToParaV1),
106}
107
108/// Version 1 payloads for [`MessageToPara`].
109#[derive(
110	Encode, Decode, DecodeWithMemTracking, Clone, Eq, PartialEq, Debug, TypeInfo, MaxEncodedLen,
111)]
112pub enum MessageToParaV1 {
113	/// Report how a registration requested with [`MessageToRelayV1::Register`] ended.
114	///
115	/// `para_id` correlates the response with its request: a parachain only sends
116	/// [`MessageToRelayV1::Register`] for a para id that is reserved and otherwise idle, so at
117	/// most one request per para id is ever in flight. `message_id` echoes the request's id on
118	/// top, tying the two together across chains and in events.
119	#[codec(index = 0)]
120	RegisterResponse {
121		/// The para id the report is about.
122		para_id: ParaId,
123		/// The id of the [`MessageToRelayV1::Register`] this answers, echoed back.
124		message_id: u64,
125		/// Whether the registration was applied on the relay chain.
126		outcome: Outcome,
127	},
128	/// Answer a [`MessageToRelayV1::CancelRegistration`].
129	///
130	/// `Ok(())` means the relay chain is no longer holding an authorization for this para id, so
131	/// the deposit can be released. The only refusal is
132	/// [`FailureReason::AlreadyRegistered`]: the code did land after all and the para is
133	/// registered, so the deposit stays where it is.
134	#[codec(index = 1)]
135	CancelResponse {
136		/// The para id the answer is about.
137		para_id: ParaId,
138		/// The id of the [`MessageToRelayV1::CancelRegistration`] this answers, echoed back.
139		message_id: u64,
140		/// Whether the authorization was dropped.
141		outcome: Outcome,
142	},
143}
144
145/// How a request ended.
146///
147/// `Ok(())` means the relay chain applied it, `Err(reason)` that it did not. Shared by every
148/// response in this protocol rather than one outcome type per request, the same way a pallet has
149/// one `Error` enum instead of one per extrinsic. Encodes as `0x00` for success and `0x01` plus
150/// the reason for failure.
151pub type Outcome = Result<(), FailureReason>;
152
153/// Why a request was rejected by the relay chain.
154#[derive(
155	Encode, Decode, DecodeWithMemTracking, Clone, Eq, PartialEq, Debug, TypeInfo, MaxEncodedLen,
156)]
157pub enum FailureReason {
158	/// The relay chain already knows this para id.
159	///
160	/// Also the answer to a [`MessageToRelayV1::CancelRegistration`] that came too late, because
161	/// the validation code landed first.
162	#[codec(index = 0)]
163	AlreadyRegistered,
164	/// The head data or the declared code length is not acceptable to the relay chain.
165	#[codec(index = 1)]
166	InvalidOnboardingData,
167	/// The relay chain is already holding as many pending registrations as it will accept.
168	#[codec(index = 3)]
169	TooManyPending,
170}
171
172/// The parachain registry, as `pallet-registrar-relay` needs to see it.
173///
174/// Implemented by whichever pallet owns parachain registration, typically `paras_registrar` on the
175/// relay chain. Lives here so neither side of the protocol has to depend on the other.
176pub trait ParachainRegistrar {
177	/// The account id used to identify a registration's manager.
178	type AccountId;
179
180	/// Whether head data and code of these sizes could be onboarded right now.
181	///
182	/// Checked against the relay chain's live configuration so a doomed request can be rejected
183	/// before the user goes and uploads megabytes of code.
184	#[allow(clippy::result_unit_err)]
185	fn check_onboarding(head_len: u32, code_len: u32) -> Result<(), ()>;
186
187	/// Whether the relay chain already knows this para id.
188	fn is_registered(para_id: ParaId) -> bool;
189
190	/// Onboard `para_id` under `manager`.
191	///
192	/// No deposit is taken: the manager's funds are held on the chain running
193	/// `pallet-registrar-para`.
194	fn register(
195		manager: Self::AccountId,
196		para_id: ParaId,
197		genesis_head: Vec<u8>,
198		validation_code: Vec<u8>,
199	) -> sp_runtime::DispatchResult;
200}