diff --git a/roadmap/implementers-guide/src/runtime/router.md b/roadmap/implementers-guide/src/runtime/router.md index f16038319392..4253453fe924 100644 --- a/roadmap/implementers-guide/src/runtime/router.md +++ b/roadmap/implementers-guide/src/runtime/router.md @@ -6,7 +6,7 @@ The Router module is responsible for all messaging mechanisms supported between Storage layout: -```rust,ignore +```rust /// Paras that are to be cleaned up at the end of the session. /// The entries are sorted ascending by the para id. OutgoingParas: Vec; @@ -31,7 +31,7 @@ DownwardMessageQueues: map ParaId => Vec; HRMP related structs: -```rust,ignore +```rust /// A description of a request to open an HRMP channel. struct HrmpOpenChannelRequest { /// Indicates if this request was confirmed by the recipient. @@ -74,7 +74,7 @@ struct HrmpChannel { ``` HRMP related storage layout -```rust,ignore +```rust /// The set of pending HRMP open channel requests. /// /// The set is accompanied by a list for iteration. @@ -115,6 +115,7 @@ HrmpEgressChannelsIndex: map ParaId => Vec; HrmpChannelContents: map HrmpChannelId => Vec; /// Maintains a mapping that can be used to answer the question: /// What paras sent a message at the given block number for a given reciever. +/// Invariant: The vector is never empty. HrmpChannelDigests: map ParaId => Vec<(BlockNumber, Vec)>; ``` @@ -135,6 +136,7 @@ Candidate Acceptance Function: 1. If the message kind is `HrmpInitOpenChannel(recipient)`: 1. Check that the `P` is not `recipient`. 1. Check that `recipient` is a valid para. + 1. Check that there is no existing channel for `(P, recipient)` in `HrmpChannels`. 1. Check that there is no existing open channel request (`P`, `recipient`) in `HrmpOpenChannelRequests`. 1. Check that the sum of the number of already opened HRMP channels by the `sender` (the size of the set found `HrmpEgressChannelsIndex` for `sender`) and the number of open requests by the @@ -142,7 +144,8 @@ Candidate Acceptance Function: channels (`config.hrmp_max_parachain_outbound_channels` or `config.hrmp_max_parathread_outbound_channels`) minus 1. 1. Check that `P`'s balance is more or equal to `config.hrmp_sender_deposit` 1. If the message kind is `HrmpAcceptOpenChannel(sender)`: - 1. Check that there is existing request between (`sender`, `P`) in `HrmpOpenChannelRequests` + 1. Check that there is an existing request between (`sender`, `P`) in `HrmpOpenChannelRequests` + 1. Check that it is not confirmed. 1. Check that `P`'s balance is more or equal to `config.hrmp_recipient_deposit`. 1. If the message kind is `HrmpCloseChannel(ch)`: 1. Check that `P` is either `ch.sender` or `ch.recipient` diff --git a/roadmap/implementers-guide/src/types/candidate.md b/roadmap/implementers-guide/src/types/candidate.md index 70191af973a8..6732d11ad8dd 100644 --- a/roadmap/implementers-guide/src/types/candidate.md +++ b/roadmap/implementers-guide/src/types/candidate.md @@ -96,6 +96,10 @@ Persisted validation data are generally derived from some relay-chain state to f The validation data also serve the purpose of giving collators a means of ensuring that their produced candidate and the commitments submitted to the relay-chain alongside it will pass the checks done by the relay-chain when backing, and give validators the same understanding when determining whether to second or attest to a candidate. +Furthermore, the validation data acts as a way to authorize the additional data the collator needs to pass to the validation +function. For example, the validation function can check whether the incoming messages (e.g. downward messages) were actually +sent by using the data provided in the validation data using so called MQC heads. + Since the commitments of the validation function are checked by the relay-chain, secondary checkers can rely on the invariant that the relay-chain only includes para-blocks for which these checks have already been done. As such, there is no need for the validation data used to inform validators and collators about the checks the relay-chain will perform to be persisted by the availability system. Nevertheless, we expose it so the backing validators can validate the outputs of a candidate before voting to submit it to the relay-chain and so collators can collate candidates that satisfy the criteria implied these transient validation data. Design-wise we should maintain two properties about this data structure: @@ -121,10 +125,12 @@ struct PersistedValidationData { parent_head: HeadData, /// The relay-chain block number this is in the context of. This informs the collator. block_number: BlockNumber, - /// The relay-chain /// The list of MQC heads for the inbound channels paired with the sender para ids. This /// vector is sorted ascending by the para id and doesn't contain multiple entries with the same /// sender. + /// + /// The MQC heads will be used by the validation function to authorize the input messages passed + /// by the collator. hrmp_mqc_heads: Vec<(ParaId, Hash)>, } ``` @@ -133,6 +139,8 @@ struct PersistedValidationData { These validation data are derived from some relay-chain state to check outputs of the validation function. +It's worth noting that all the data is collected **before** the candidate execution. + ```rust struct TransientValidationData { /// The maximum code size permitted, in bytes, of a produced validation code upgrade. @@ -159,6 +167,53 @@ struct TransientValidationData { /// /// This informs a relay-chain backing check and the parachain logic. code_upgrade_allowed: Option, + /// A copy of `config.max_upward_message_num_per_candidate` for checking that a candidate doesn't + /// send more messages that permitted. + config_max_upward_message_num_per_candidate: u32, + /// The number of messages pending of the downward message queue. + dmq_length: u32, + /// A part of transient validation data related to HRMP. + hrmp: HrmpTransientValidationData, +} + +struct HrmpTransientValidationData { + /// A vector that enumerates the list of blocks in which there was at least one HRMP message + /// received. + /// + /// The first number in the vector, if any, is always greater than the HRMP watermark. The + /// elements are ordered by ascending the block number. The vector doesn't contain duplicates. + digest: Vec, + /// The watermark of the HRMP. That is, the block number up to which (inclusive) all HRMP messages + /// sent to the parachain are processed. + watermark: BlockNumber, + /// A mapping that specifies if the parachain can send an HRMP message to the given recipient + /// channel. A candidate can send a message only to the recipients that are present in this + /// mapping. The number elements in this vector corresponds to the number of egress channels. + /// Since it's a mapping there can't be two items with same `ParaId`. + egress_limits: Vec<(ParaId, HrmpChannelLimits)>, + /// A vector of paras that have a channel to this para. The number of elements in this vector + /// correponds to the number of ingress channels. The items are ordered ascending by `ParaId`. + /// The vector doesn't contain two entries with the same `ParaId`. + ingress_senders: Vec, + /// A vector of open requests in which the para participates either as sender or recipient. The + /// items are ordered ascending by `HrmpChannelId`. The vector doesn't contain two entries + /// with the same `HrmpChannelId`. + open_requests: Vec<(HrmpChannelId, HrmpAbridgedOpenChannelRequest)>, + /// A vector of close requests in which the para participates either as sender or recipient. + /// The vector doesn't contain two entries with the same `HrmpChannelId`. + close_requests: Vec, +} + +/// A shorter version of `HrmpOpenChannelRequest`. +struct HrmpAbridgedOpenChannelRequest { + confirmed: bool, +} + +struct HrmpChannelLimits { + /// Indicates if the channel is already full and cannot accept any more messages. + is_full: bool, + /// A message sent to the channel can occupy only that many bytes. + available_size: u32, } ``` diff --git a/roadmap/implementers-guide/src/types/messages.md b/roadmap/implementers-guide/src/types/messages.md index 315923e3117c..ba77a9ecbc10 100644 --- a/roadmap/implementers-guide/src/types/messages.md +++ b/roadmap/implementers-guide/src/types/messages.md @@ -14,6 +14,8 @@ that we use the first item tuple for the sender and the second for the recipient is allowed between two participants in one direction, i.e. there cannot be 2 different channels identified by `(A, B)`. +`HrmpChannelId` has a defined ordering: first `sender` and tie is resolved by `recipient`. + ```rust,ignore struct HrmpChannelId { sender: ParaId,