mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 05:51:02 +00:00
* Add markdown linting
- add linter default rules
- adapt rules to current code
- fix the code for linting to pass
- add CI check
fix #1243
* Fix markdown for Substrate
* Fix tooling install
* Fix workflow
* Add documentation
* Remove trailing spaces
* Update .github/.markdownlint.yaml
Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
* Fix mangled markdown/lists
* Fix captalization issues on known words
(cherry picked from commit a30092ab42)
Co-authored-by: Chevdor <chevdor@users.noreply.github.com>
This commit is contained in:
committed by
Bastian Köcher
parent
2c26640ac3
commit
91e5fc1e6d
+145
-172
@@ -1,8 +1,7 @@
|
||||
# Bridge Messages Pallet
|
||||
|
||||
The messages pallet is used to deliver messages from source chain to target chain. Message is
|
||||
(almost) opaque to the module and the final goal is to hand message to the message dispatch
|
||||
mechanism.
|
||||
The messages pallet is used to deliver messages from source chain to target chain. Message is (almost) opaque to the
|
||||
module and the final goal is to hand message to the message dispatch mechanism.
|
||||
|
||||
## Contents
|
||||
|
||||
@@ -14,229 +13,203 @@ mechanism.
|
||||
|
||||
## Overview
|
||||
|
||||
Message lane is an unidirectional channel, where messages are sent from source chain to the target
|
||||
chain. At the same time, a single instance of messages module supports both outbound lanes and
|
||||
inbound lanes. So the chain where the module is deployed (this chain), may act as a source chain for
|
||||
outbound messages (heading to a bridged chain) and as a target chain for inbound messages (coming
|
||||
from a bridged chain).
|
||||
Message lane is an unidirectional channel, where messages are sent from source chain to the target chain. At the same
|
||||
time, a single instance of messages module supports both outbound lanes and inbound lanes. So the chain where the module
|
||||
is deployed (this chain), may act as a source chain for outbound messages (heading to a bridged chain) and as a target
|
||||
chain for inbound messages (coming from a bridged chain).
|
||||
|
||||
Messages module supports multiple message lanes. Every message lane is identified with a 4-byte
|
||||
identifier. Messages sent through the lane are assigned unique (for this lane) increasing integer
|
||||
value that is known as nonce ("number that can only be used once"). Messages that are sent over the
|
||||
same lane are guaranteed to be delivered to the target chain in the same order they're sent from
|
||||
the source chain. In other words, message with nonce `N` will be delivered right before delivering a
|
||||
message with nonce `N+1`.
|
||||
Messages module supports multiple message lanes. Every message lane is identified with a 4-byte identifier. Messages
|
||||
sent through the lane are assigned unique (for this lane) increasing integer value that is known as nonce ("number that
|
||||
can only be used once"). Messages that are sent over the same lane are guaranteed to be delivered to the target chain in
|
||||
the same order they're sent from the source chain. In other words, message with nonce `N` will be delivered right before
|
||||
delivering a message with nonce `N+1`.
|
||||
|
||||
Single message lane may be seen as a transport channel for single application (onchain, offchain or
|
||||
mixed). At the same time the module itself never dictates any lane or message rules. In the end, it
|
||||
is the runtime developer who defines what message lane and message mean for this runtime.
|
||||
Single message lane may be seen as a transport channel for single application (onchain, offchain or mixed). At the same
|
||||
time the module itself never dictates any lane or message rules. In the end, it is the runtime developer who defines
|
||||
what message lane and message mean for this runtime.
|
||||
|
||||
In our [Kusama<>Polkadot bridge](../../docs/polkadot-kusama-bridge-overview.md) we are using lane
|
||||
as a channel of communication between two parachains of different relay chains. For example, lane
|
||||
`[0, 0, 0, 0]` is used for Polkadot <> Kusama Asset Hub communications. Other lanes may be used to
|
||||
bridge other parachains.
|
||||
In our [Kusama<>Polkadot bridge](../../docs/polkadot-kusama-bridge-overview.md) we are using lane as a channel of
|
||||
communication between two parachains of different relay chains. For example, lane `[0, 0, 0, 0]` is used for Polkadot <>
|
||||
Kusama Asset Hub communications. Other lanes may be used to bridge other parachains.
|
||||
|
||||
## Message Workflow
|
||||
|
||||
The pallet is not intended to be used by end users and provides no public calls to send the message.
|
||||
Instead, it provides runtime-internal method that allows other pallets (or other runtime code) to queue
|
||||
outbound messages.
|
||||
The pallet is not intended to be used by end users and provides no public calls to send the message. Instead, it
|
||||
provides runtime-internal method that allows other pallets (or other runtime code) to queue outbound messages.
|
||||
|
||||
The message "appears" when some runtime code calls the `send_message()` method of the pallet.
|
||||
The submitter specifies the lane that they're willing to use and the message itself. If some fee must
|
||||
be paid for sending the message, it must be paid outside of the pallet. If a message passes all checks
|
||||
(that include, for example, message size check, disabled lane check, ...), the nonce is assigned and
|
||||
the message is stored in the module storage. The message is in an "undelivered" state now.
|
||||
The message "appears" when some runtime code calls the `send_message()` method of the pallet. The submitter specifies
|
||||
the lane that they're willing to use and the message itself. If some fee must be paid for sending the message, it must
|
||||
be paid outside of the pallet. If a message passes all checks (that include, for example, message size check, disabled
|
||||
lane check, ...), the nonce is assigned and the message is stored in the module storage. The message is in an
|
||||
"undelivered" state now.
|
||||
|
||||
We assume that there are external, offchain actors, called relayers, that are submitting module
|
||||
related transactions to both target and source chains. The pallet itself has no assumptions about
|
||||
relayers incentivization scheme, but it has some callbacks for paying rewards. See
|
||||
[Integrating Messages Module into runtime](#Integrating-Messages-Module-into-runtime)
|
||||
for details.
|
||||
We assume that there are external, offchain actors, called relayers, that are submitting module related transactions to
|
||||
both target and source chains. The pallet itself has no assumptions about relayers incentivization scheme, but it has
|
||||
some callbacks for paying rewards. See [Integrating Messages Module into
|
||||
runtime](#Integrating-Messages-Module-into-runtime) for details.
|
||||
|
||||
Eventually, some relayer would notice this message in the "undelivered" state and it would decide to
|
||||
deliver this message. Relayer then crafts `receive_messages_proof()` transaction (aka delivery
|
||||
transaction) for the messages module instance, deployed at the target chain. Relayer provides
|
||||
its account id at the source chain, the proof of message (or several messages), the number of
|
||||
messages in the transaction and their cumulative dispatch weight. Once a transaction is mined, the
|
||||
message is considered "delivered".
|
||||
Eventually, some relayer would notice this message in the "undelivered" state and it would decide to deliver this
|
||||
message. Relayer then crafts `receive_messages_proof()` transaction (aka delivery transaction) for the messages module
|
||||
instance, deployed at the target chain. Relayer provides its account id at the source chain, the proof of message (or
|
||||
several messages), the number of messages in the transaction and their cumulative dispatch weight. Once a transaction is
|
||||
mined, the message is considered "delivered".
|
||||
|
||||
Once a message is delivered, the relayer may want to confirm delivery back to the source chain.
|
||||
There are two reasons why it would want to do that. The first is that we intentionally limit number
|
||||
of "delivered", but not yet "confirmed" messages at inbound lanes
|
||||
(see [What about other Constants in the Messages Module Configuration Trait](#What-about-other-Constants-in-the-Messages-Module-Configuration-Trait) for explanation).
|
||||
So at some point, the target chain may stop accepting new messages until relayers confirm some of
|
||||
these. The second is that if the relayer wants to be rewarded for delivery, it must prove the fact
|
||||
that it has actually delivered the message. And this proof may only be generated after the delivery
|
||||
transaction is mined. So relayer crafts the `receive_messages_delivery_proof()` transaction (aka
|
||||
confirmation transaction) for the messages module instance, deployed at the source chain. Once
|
||||
this transaction is mined, the message is considered "confirmed".
|
||||
Once a message is delivered, the relayer may want to confirm delivery back to the source chain. There are two reasons
|
||||
why it would want to do that. The first is that we intentionally limit number of "delivered", but not yet "confirmed"
|
||||
messages at inbound lanes (see [What about other Constants in the Messages Module Configuration
|
||||
Trait](#What-about-other-Constants-in-the-Messages-Module-Configuration-Trait) for explanation). So at some point, the
|
||||
target chain may stop accepting new messages until relayers confirm some of these. The second is that if the relayer
|
||||
wants to be rewarded for delivery, it must prove the fact that it has actually delivered the message. And this proof may
|
||||
only be generated after the delivery transaction is mined. So relayer crafts the `receive_messages_delivery_proof()`
|
||||
transaction (aka confirmation transaction) for the messages module instance, deployed at the source chain. Once this
|
||||
transaction is mined, the message is considered "confirmed".
|
||||
|
||||
The "confirmed" state is the final state of the message. But there's one last thing related to the
|
||||
message - the fact that it is now "confirmed" and reward has been paid to the relayer (or at least
|
||||
callback for this has been called), must be confirmed to the target chain. Otherwise, we may reach
|
||||
the limit of "unconfirmed" messages at the target chain and it will stop accepting new messages. So
|
||||
relayer sometimes includes a nonce of the latest "confirmed" message in the next
|
||||
The "confirmed" state is the final state of the message. But there's one last thing related to the message - the fact
|
||||
that it is now "confirmed" and reward has been paid to the relayer (or at least callback for this has been called), must
|
||||
be confirmed to the target chain. Otherwise, we may reach the limit of "unconfirmed" messages at the target chain and it
|
||||
will stop accepting new messages. So relayer sometimes includes a nonce of the latest "confirmed" message in the next
|
||||
`receive_messages_proof()` transaction, proving that some messages have been confirmed.
|
||||
|
||||
## Integrating Messages Module into Runtime
|
||||
|
||||
As it has been said above, the messages module supports both outbound and inbound message lanes.
|
||||
So if we will integrate a module in some runtime, it may act as the source chain runtime for
|
||||
outbound messages and as the target chain runtime for inbound messages. In this section, we'll
|
||||
sometimes refer to the chain we're currently integrating with, as "this chain" and the other
|
||||
chain as "bridged chain".
|
||||
As it has been said above, the messages module supports both outbound and inbound message lanes. So if we will integrate
|
||||
a module in some runtime, it may act as the source chain runtime for outbound messages and as the target chain runtime
|
||||
for inbound messages. In this section, we'll sometimes refer to the chain we're currently integrating with, as "this
|
||||
chain" and the other chain as "bridged chain".
|
||||
|
||||
Messages module doesn't simply accept transactions that are claiming that the bridged chain has
|
||||
some updated data for us. Instead of this, the module assumes that the bridged chain is able to
|
||||
prove that updated data in some way. The proof is abstracted from the module and may be of any kind.
|
||||
In our Substrate-to-Substrate bridge we're using runtime storage proofs. Other bridges may use
|
||||
transaction proofs, Substrate header digests or anything else that may be proved.
|
||||
Messages module doesn't simply accept transactions that are claiming that the bridged chain has some updated data for
|
||||
us. Instead of this, the module assumes that the bridged chain is able to prove that updated data in some way. The proof
|
||||
is abstracted from the module and may be of any kind. In our Substrate-to-Substrate bridge we're using runtime storage
|
||||
proofs. Other bridges may use transaction proofs, Substrate header digests or anything else that may be proved.
|
||||
|
||||
**IMPORTANT NOTE**: everything below in this chapter describes details of the messages module
|
||||
configuration. But if you're interested in well-probed and relatively easy integration of two
|
||||
Substrate-based chains, you may want to look at the
|
||||
[bridge-runtime-common](../../bin/runtime-common/) crate. This crate is providing a lot of
|
||||
helpers for integration, which may be directly used from within your runtime. Then if you'll decide
|
||||
to change something in this scheme, get back here for detailed information.
|
||||
**IMPORTANT NOTE**: everything below in this chapter describes details of the messages module configuration. But if
|
||||
you're interested in well-probed and relatively easy integration of two Substrate-based chains, you may want to look at
|
||||
the [bridge-runtime-common](../../bin/runtime-common/) crate. This crate is providing a lot of helpers for integration,
|
||||
which may be directly used from within your runtime. Then if you'll decide to change something in this scheme, get back
|
||||
here for detailed information.
|
||||
|
||||
### General Information
|
||||
|
||||
The messages module supports instances. Every module instance is supposed to bridge this chain
|
||||
and some bridged chain. To bridge with another chain, using another instance is suggested (this
|
||||
isn't forced anywhere in the code, though). Keep in mind, that the pallet may be used to build
|
||||
virtual channels between multiple chains, as we do in our [Polkadot <> Kusama bridge](../../docs/polkadot-kusama-bridge-overview.md).
|
||||
There, the pallet actually bridges only two parachains - Kusama Bridge Hub and Polkadot
|
||||
Bridge Hub. However, other Kusama and Polkadot parachains are able to send (XCM) messages to their
|
||||
Bridge Hubs. The messages will be delivered to the other side of the bridge and routed to the proper
|
||||
The messages module supports instances. Every module instance is supposed to bridge this chain and some bridged chain.
|
||||
To bridge with another chain, using another instance is suggested (this isn't forced anywhere in the code, though). Keep
|
||||
in mind, that the pallet may be used to build virtual channels between multiple chains, as we do in our [Polkadot <>
|
||||
Kusama bridge](../../docs/polkadot-kusama-bridge-overview.md). There, the pallet actually bridges only two parachains -
|
||||
Kusama Bridge Hub and Polkadot Bridge Hub. However, other Kusama and Polkadot parachains are able to send (XCM) messages
|
||||
to their Bridge Hubs. The messages will be delivered to the other side of the bridge and routed to the proper
|
||||
destination parachain within the bridged chain consensus.
|
||||
|
||||
Message submitters may track message progress by inspecting module events. When Message is accepted,
|
||||
the `MessageAccepted` event is emitted. The event contains both message lane identifier and nonce that
|
||||
has been assigned to the message. When a message is delivered to the target chain, the `MessagesDelivered`
|
||||
event is emitted from the `receive_messages_delivery_proof()` transaction. The `MessagesDelivered` contains
|
||||
the message lane identifier and inclusive range of delivered message nonces.
|
||||
Message submitters may track message progress by inspecting module events. When Message is accepted, the
|
||||
`MessageAccepted` event is emitted. The event contains both message lane identifier and nonce that has been assigned to
|
||||
the message. When a message is delivered to the target chain, the `MessagesDelivered` event is emitted from the
|
||||
`receive_messages_delivery_proof()` transaction. The `MessagesDelivered` contains the message lane identifier and
|
||||
inclusive range of delivered message nonces.
|
||||
|
||||
The pallet provides no means to get the result of message dispatch at the target chain. If that is
|
||||
required, it must be done outside of the pallet. For example, XCM messages, when dispatched, have
|
||||
special instructions to send some data back to the sender. Other dispatchers may use similar
|
||||
mechanism for that.
|
||||
The pallet provides no means to get the result of message dispatch at the target chain. If that is required, it must be
|
||||
done outside of the pallet. For example, XCM messages, when dispatched, have special instructions to send some data back
|
||||
to the sender. Other dispatchers may use similar mechanism for that.
|
||||
### How to plug-in Messages Module to Send Messages to the Bridged Chain?
|
||||
|
||||
The `pallet_bridge_messages::Config` trait has 3 main associated types that are used to work with
|
||||
outbound messages. The `pallet_bridge_messages::Config::TargetHeaderChain` defines how we see the
|
||||
bridged chain as the target for our outbound messages. It must be able to check that the bridged
|
||||
chain may accept our message - like that the message has size below maximal possible transaction
|
||||
size of the chain and so on. And when the relayer sends us a confirmation transaction, this
|
||||
implementation must be able to parse and verify the proof of messages delivery. Normally, you would
|
||||
reuse the same (configurable) type on all chains that are sending messages to the same bridged
|
||||
chain.
|
||||
The `pallet_bridge_messages::Config` trait has 3 main associated types that are used to work with outbound messages. The
|
||||
`pallet_bridge_messages::Config::TargetHeaderChain` defines how we see the bridged chain as the target for our outbound
|
||||
messages. It must be able to check that the bridged chain may accept our message - like that the message has size below
|
||||
maximal possible transaction size of the chain and so on. And when the relayer sends us a confirmation transaction, this
|
||||
implementation must be able to parse and verify the proof of messages delivery. Normally, you would reuse the same
|
||||
(configurable) type on all chains that are sending messages to the same bridged chain.
|
||||
|
||||
The `pallet_bridge_messages::Config::LaneMessageVerifier` defines a single callback to verify outbound
|
||||
messages. The simplest callback may just accept all messages. But in this case you'll need to answer
|
||||
many questions first. Who will pay for the delivery and confirmation transaction? Are we sure that
|
||||
someone will ever deliver this message to the bridged chain? Are we sure that we don't bloat our
|
||||
runtime storage by accepting this message? What if the message is improperly encoded or has some
|
||||
fields set to invalid values? Answering all those (and similar) questions would lead to correct
|
||||
implementation.
|
||||
The `pallet_bridge_messages::Config::LaneMessageVerifier` defines a single callback to verify outbound messages. The
|
||||
simplest callback may just accept all messages. But in this case you'll need to answer many questions first. Who will
|
||||
pay for the delivery and confirmation transaction? Are we sure that someone will ever deliver this message to the
|
||||
bridged chain? Are we sure that we don't bloat our runtime storage by accepting this message? What if the message is
|
||||
improperly encoded or has some fields set to invalid values? Answering all those (and similar) questions would lead to
|
||||
correct implementation.
|
||||
|
||||
There's another thing to consider when implementing type for use in
|
||||
`pallet_bridge_messages::Config::LaneMessageVerifier`. It is whether we treat all message lanes
|
||||
identically, or they'll have different sets of verification rules? For example, you may reserve
|
||||
lane#1 for messages coming from some 'wrapped-token' pallet - then you may verify in your
|
||||
implementation that the origin is associated with this pallet. Lane#2 may be reserved for 'system'
|
||||
messages and you may charge zero fee for such messages. You may have some rate limiting for messages
|
||||
sent over the lane#3. Or you may just verify the same rules set for all outbound messages - it is
|
||||
`pallet_bridge_messages::Config::LaneMessageVerifier`. It is whether we treat all message lanes identically, or they'll
|
||||
have different sets of verification rules? For example, you may reserve lane#1 for messages coming from some
|
||||
'wrapped-token' pallet - then you may verify in your implementation that the origin is associated with this pallet.
|
||||
Lane#2 may be reserved for 'system' messages and you may charge zero fee for such messages. You may have some rate
|
||||
limiting for messages sent over the lane#3. Or you may just verify the same rules set for all outbound messages - it is
|
||||
all up to the `pallet_bridge_messages::Config::LaneMessageVerifier` implementation.
|
||||
|
||||
The last type is the `pallet_bridge_messages::Config::DeliveryConfirmationPayments`. When confirmation
|
||||
transaction is received, we call the `pay_reward()` method, passing the range of delivered messages.
|
||||
You may use the [`pallet-bridge-relayers`](../relayers/) pallet and its
|
||||
[`DeliveryConfirmationPaymentsAdapter`](../relayers/src/payment_adapter.rs) adapter as a possible
|
||||
implementation. It allows you to pay fixed reward for relaying the message and some of its portion
|
||||
for confirming delivery.
|
||||
The last type is the `pallet_bridge_messages::Config::DeliveryConfirmationPayments`. When confirmation transaction is
|
||||
received, we call the `pay_reward()` method, passing the range of delivered messages. You may use the
|
||||
[`pallet-bridge-relayers`](../relayers/) pallet and its
|
||||
[`DeliveryConfirmationPaymentsAdapter`](../relayers/src/payment_adapter.rs) adapter as a possible implementation. It
|
||||
allows you to pay fixed reward for relaying the message and some of its portion for confirming delivery.
|
||||
|
||||
### I have a Messages Module in my Runtime, but I Want to Reject all Outbound Messages. What shall I do?
|
||||
|
||||
You should be looking at the `bp_messages::source_chain::ForbidOutboundMessages` structure
|
||||
[`bp_messages::source_chain`](../../primitives/messages/src/source_chain.rs). It implements
|
||||
all required traits and will simply reject all transactions, related to outbound messages.
|
||||
[`bp_messages::source_chain`](../../primitives/messages/src/source_chain.rs). It implements all required traits and will
|
||||
simply reject all transactions, related to outbound messages.
|
||||
|
||||
### How to plug-in Messages Module to Receive Messages from the Bridged Chain?
|
||||
|
||||
The `pallet_bridge_messages::Config` trait has 2 main associated types that are used to work with
|
||||
inbound messages. The `pallet_bridge_messages::Config::SourceHeaderChain` defines how we see the
|
||||
bridged chain as the source of our inbound messages. When relayer sends us a delivery transaction,
|
||||
this implementation must be able to parse and verify the proof of messages wrapped in this
|
||||
transaction. Normally, you would reuse the same (configurable) type on all chains that are sending
|
||||
messages to the same bridged chain.
|
||||
The `pallet_bridge_messages::Config` trait has 2 main associated types that are used to work with inbound messages. The
|
||||
`pallet_bridge_messages::Config::SourceHeaderChain` defines how we see the bridged chain as the source of our inbound
|
||||
messages. When relayer sends us a delivery transaction, this implementation must be able to parse and verify the proof
|
||||
of messages wrapped in this transaction. Normally, you would reuse the same (configurable) type on all chains that are
|
||||
sending messages to the same bridged chain.
|
||||
|
||||
The `pallet_bridge_messages::Config::MessageDispatch` defines a way on how to dispatch delivered
|
||||
messages. Apart from actually dispatching the message, the implementation must return the correct
|
||||
dispatch weight of the message before dispatch is called.
|
||||
The `pallet_bridge_messages::Config::MessageDispatch` defines a way on how to dispatch delivered messages. Apart from
|
||||
actually dispatching the message, the implementation must return the correct dispatch weight of the message before
|
||||
dispatch is called.
|
||||
|
||||
### I have a Messages Module in my Runtime, but I Want to Reject all Inbound Messages. What shall I do?
|
||||
|
||||
You should be looking at the `bp_messages::target_chain::ForbidInboundMessages` structure from
|
||||
the [`bp_messages::target_chain`](../../primitives/messages/src/target_chain.rs) module. It
|
||||
implements all required traits and will simply reject all transactions, related to inbound messages.
|
||||
You should be looking at the `bp_messages::target_chain::ForbidInboundMessages` structure from the
|
||||
[`bp_messages::target_chain`](../../primitives/messages/src/target_chain.rs) module. It implements all required traits
|
||||
and will simply reject all transactions, related to inbound messages.
|
||||
|
||||
### What about other Constants in the Messages Module Configuration Trait?
|
||||
|
||||
Two settings that are used to check messages in the `send_message()` function. The
|
||||
`pallet_bridge_messages::Config::ActiveOutboundLanes` is an array of all message lanes, that
|
||||
may be used to send messages. All messages sent using other lanes are rejected. All messages that have
|
||||
size above `pallet_bridge_messages::Config::MaximalOutboundPayloadSize` will also be rejected.
|
||||
`pallet_bridge_messages::Config::ActiveOutboundLanes` is an array of all message lanes, that may be used to send
|
||||
messages. All messages sent using other lanes are rejected. All messages that have size above
|
||||
`pallet_bridge_messages::Config::MaximalOutboundPayloadSize` will also be rejected.
|
||||
|
||||
To be able to reward the relayer for delivering messages, we store a map of message nonces range =>
|
||||
identifier of the relayer that has delivered this range at the target chain runtime storage. If a
|
||||
relayer delivers multiple consequent ranges, they're merged into single entry. So there may be more
|
||||
than one entry for the same relayer. Eventually, this whole map must be delivered back to the source
|
||||
chain to confirm delivery and pay rewards. So to make sure we are able to craft this confirmation
|
||||
transaction, we need to: (1) keep the size of this map below a certain limit and (2) make sure that
|
||||
the weight of processing this map is below a certain limit. Both size and processing weight mostly
|
||||
depend on the number of entries. The number of entries is limited with the
|
||||
`pallet_bridge_messages::ConfigMaxUnrewardedRelayerEntriesAtInboundLane` parameter. Processing weight
|
||||
also depends on the total number of messages that are being confirmed, because every confirmed
|
||||
message needs to be read. So there's another
|
||||
`pallet_bridge_messages::Config::MaxUnconfirmedMessagesAtInboundLane` parameter for that.
|
||||
To be able to reward the relayer for delivering messages, we store a map of message nonces range => identifier of the
|
||||
relayer that has delivered this range at the target chain runtime storage. If a relayer delivers multiple consequent
|
||||
ranges, they're merged into single entry. So there may be more than one entry for the same relayer. Eventually, this
|
||||
whole map must be delivered back to the source chain to confirm delivery and pay rewards. So to make sure we are able to
|
||||
craft this confirmation transaction, we need to: (1) keep the size of this map below a certain limit and (2) make sure
|
||||
that the weight of processing this map is below a certain limit. Both size and processing weight mostly depend on the
|
||||
number of entries. The number of entries is limited with the
|
||||
`pallet_bridge_messages::ConfigMaxUnrewardedRelayerEntriesAtInboundLane` parameter. Processing weight also depends on
|
||||
the total number of messages that are being confirmed, because every confirmed message needs to be read. So there's
|
||||
another `pallet_bridge_messages::Config::MaxUnconfirmedMessagesAtInboundLane` parameter for that.
|
||||
|
||||
When choosing values for these parameters, you must also keep in mind that if proof in your scheme
|
||||
is based on finality of headers (and it is the most obvious option for Substrate-based chains with
|
||||
finality notion), then choosing too small values for these parameters may cause significant delays
|
||||
in message delivery. That's because there are too many actors involved in this scheme: 1) authorities
|
||||
that are finalizing headers of the target chain need to finalize header with non-empty map; 2) the
|
||||
headers relayer then needs to submit this header and its finality proof to the source chain; 3) the
|
||||
messages relayer must then send confirmation transaction (storage proof of this map) to the source
|
||||
chain; 4) when the confirmation transaction will be mined at some header, source chain authorities
|
||||
must finalize this header; 5) the headers relay then needs to submit this header and its finality
|
||||
proof to the target chain; 6) only now the messages relayer may submit new messages from the source
|
||||
to target chain and prune the entry from the map.
|
||||
When choosing values for these parameters, you must also keep in mind that if proof in your scheme is based on finality
|
||||
of headers (and it is the most obvious option for Substrate-based chains with finality notion), then choosing too small
|
||||
values for these parameters may cause significant delays in message delivery. That's because there are too many actors
|
||||
involved in this scheme: 1) authorities that are finalizing headers of the target chain need to finalize header with
|
||||
non-empty map; 2) the headers relayer then needs to submit this header and its finality proof to the source chain; 3)
|
||||
the messages relayer must then send confirmation transaction (storage proof of this map) to the source chain; 4) when
|
||||
the confirmation transaction will be mined at some header, source chain authorities must finalize this header; 5) the
|
||||
headers relay then needs to submit this header and its finality proof to the target chain; 6) only now the messages
|
||||
relayer may submit new messages from the source to target chain and prune the entry from the map.
|
||||
|
||||
Delivery transaction requires the relayer to provide both number of entries and total number of
|
||||
messages in the map. This means that the module never charges an extra cost for delivering a map -
|
||||
the relayer would need to pay exactly for the number of entries+messages it has delivered. So the
|
||||
best guess for values of these parameters would be the pair that would occupy `N` percent of the
|
||||
maximal transaction size and weight of the source chain. The `N` should be large enough to process
|
||||
large maps, at the same time keeping reserve for future source chain upgrades.
|
||||
Delivery transaction requires the relayer to provide both number of entries and total number of messages in the map.
|
||||
This means that the module never charges an extra cost for delivering a map - the relayer would need to pay exactly for
|
||||
the number of entries+messages it has delivered. So the best guess for values of these parameters would be the pair that
|
||||
would occupy `N` percent of the maximal transaction size and weight of the source chain. The `N` should be large enough
|
||||
to process large maps, at the same time keeping reserve for future source chain upgrades.
|
||||
|
||||
## Non-Essential Functionality
|
||||
|
||||
There may be a special account in every runtime where the messages module is deployed. This
|
||||
account, named 'module owner', is like a module-level sudo account - he's able to halt and
|
||||
resume all module operations without requiring runtime upgrade. Calls that are related to this
|
||||
account are:
|
||||
There may be a special account in every runtime where the messages module is deployed. This account, named 'module
|
||||
owner', is like a module-level sudo account - he's able to halt and resume all module operations without requiring
|
||||
runtime upgrade. Calls that are related to this account are:
|
||||
- `fn set_owner()`: current module owner may call it to transfer "ownership" to another account;
|
||||
- `fn halt_operations()`: the module owner (or sudo account) may call this function to stop all
|
||||
module operations. After this call, all message-related transactions will be rejected until
|
||||
further `resume_operations` call'. This call may be used when something extraordinary happens with
|
||||
the bridge;
|
||||
- `fn resume_operations()`: module owner may call this function to resume bridge operations. The
|
||||
module will resume its regular operations after this call.
|
||||
- `fn halt_operations()`: the module owner (or sudo account) may call this function to stop all module operations. After
|
||||
this call, all message-related transactions will be rejected until further `resume_operations` call'. This call may be
|
||||
used when something extraordinary happens with the bridge;
|
||||
- `fn resume_operations()`: module owner may call this function to resume bridge operations. The module will resume its
|
||||
regular operations after this call.
|
||||
|
||||
If pallet owner is not defined, the governance may be used to make those calls.
|
||||
|
||||
## Messages Relay
|
||||
|
||||
We have an offchain actor, who is watching for new messages and submits them to the bridged chain.
|
||||
It is the messages relay - you may look at the [crate level documentation and the code](../../relays/messages/).
|
||||
We have an offchain actor, who is watching for new messages and submits them to the bridged chain. It is the messages
|
||||
relay - you may look at the [crate level documentation and the code](../../relays/messages/).
|
||||
|
||||
@@ -19,7 +19,7 @@ validators. Validators validate the block and register the new parachain head in
|
||||
[`Heads` map](https://github.com/paritytech/polkadot/blob/88013730166ba90745ae7c9eb3e0c1be1513c7cc/runtime/parachains/src/paras/mod.rs#L645)
|
||||
of the [`paras`](https://github.com/paritytech/polkadot/tree/master/runtime/parachains/src/paras) pallet,
|
||||
deployed at the relay chain. Keep in mind that this pallet, deployed at a relay chain, is **NOT** a bridge pallet,
|
||||
even though the names are similar.
|
||||
even though the names are similar.
|
||||
|
||||
And what the bridge parachains pallet does, is simply verifying storage proofs of parachain heads within that
|
||||
`Heads` map. It does that using relay chain header, that has been previously imported by the
|
||||
|
||||
Reference in New Issue
Block a user