Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Commit

Permalink
Implementer's Guide: Incorporate HRMP to TransientValidationData (#1588)
Browse files Browse the repository at this point in the history
* Add a note about time of collection of TransientValidationData

* Add HRMP digest and dmq length to TransientValidationData

* Add a note that the vector in hrmp digest is never empty

* Add hrmp watermark to TransientValidationData

* Add HRMP egress limits

* Incorporate the latest dispatchable upward messages changes.

* Update candidate.md

* Update candidate.md docs

* Fix wording

* Delete assignmets.md

* Update roadmap/implementers-guide/src/types/candidate.md

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* Extract HrmpTransientValidationData and add additional data.

* Some clarifications.

* Introduce HrmpAbridgedOpenChannelRequest

* Update roadmap/implementers-guide/src/types/candidate.md

Co-authored-by: Bernhard Schuster <bernhard@ahoi.io>

* Fix typo: egress->ingress

* A note about sorting

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
Co-authored-by: Bernhard Schuster <bernhard@ahoi.io>
  • Loading branch information
3 people authored Aug 31, 2020
1 parent 0af385c commit f125cbe
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 5 deletions.
11 changes: 7 additions & 4 deletions roadmap/implementers-guide/src/runtime/router.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<ParaId>;
Expand All @@ -31,7 +31,7 @@ DownwardMessageQueues: map ParaId => Vec<DownwardMessage>;

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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -115,6 +115,7 @@ HrmpEgressChannelsIndex: map ParaId => Vec<ParaId>;
HrmpChannelContents: map HrmpChannelId => Vec<InboundHrmpMessage>;
/// 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<ParaId>)>;
```

Expand All @@ -135,14 +136,16 @@ 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
`sender` (the value from `HrmpOpenChannelRequestCount` for `sender`) doesn't exceed the limit of
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`
Expand Down
57 changes: 56 additions & 1 deletion roadmap/implementers-guide/src/types/candidate.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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)>,
}
```
Expand All @@ -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.
Expand All @@ -159,6 +167,53 @@ struct TransientValidationData {
///
/// This informs a relay-chain backing check and the parachain logic.
code_upgrade_allowed: Option<BlockNumber>,
/// 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<BlockNumber>,
/// 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<ParaId>,
/// 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<HrmpChannelId>,
}

/// 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,
}
```

Expand Down
2 changes: 2 additions & 0 deletions roadmap/implementers-guide/src/types/messages.md
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit f125cbe

Please sign in to comment.