-
Notifications
You must be signed in to change notification settings - Fork 88
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs(data flow): refine tx & l1tol2 messaging & add l2tol1 messaging (#…
…843) * docs(data flow): refine tx inclusion * docs(data flow): refine l1 to l2 messaging and add en-US version * docs(data flow): add l2 to l1 messaging --------- Co-authored-by: triplex <[email protected]> Co-authored-by: popcnt-subodhi <subodhi@west>
- Loading branch information
1 parent
69c5d6c
commit 529a876
Showing
10 changed files
with
361 additions
and
117 deletions.
There are no files selected for viewing
72 changes: 72 additions & 0 deletions
72
docs/website/pages/docs/tech-highlights/l1_to_l2_messaging.en-US.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
## L1 to L2 Messaging | ||
|
||
## Overview | ||
|
||
L1 to L2 messaging is implemented by L1 triggered L2 transactions. (Asset transfers are based on this mechanism) | ||
|
||
Rooch has the ability of multi-chain asset settlement, for each L1, its L1 to L2 process is the same (note: the contract name and its parameters are slightly different on L1 due to different smart contract languages), it is the light node on Rooch that verifies the event from L1 and then executes the L2 transaction: | ||
|
||
<img alt="L1 to L2 Messaging" height="400" src="/docs/l1tol2.jpeg" width="800"/> | ||
|
||
## L1 | ||
|
||
L1 needs to generate events for L2 calls that contain all the information needed for the L2 call and the process that took place on L1, which will be parsed by the `rooch_node` and relayed to L2. | ||
|
||
1. The user initiates the L1 to L2 request by calling the `call_remote` function in `l1_stub` with the following parameters. | ||
1. `action`: the encoded Rooch MoveAction 2. | ||
2. `min_gas_amount`: the minimum amount of gas allowed on L2, i.e. an estimate of the value of the call `action`. | ||
Considering the processing overhead that L2 requires before calling `action`, the actual overhead will definitely exceed this value. See [Gas Fees](#gas-fees) for details. | ||
|
||
`l1_stub` provides a more user-friendly interface, where the caller only needs to be concerned with the L2 call information and not with message encapsulation and delivery. | ||
|
||
2. `l1_stub` will call the `send_l1_to_l2` function of `rooch_transport` to accomplish event logging and gas burning on L1 with the following parameters: | ||
1. `msg_sequence | ||
2. `msg_sender | ||
3. `action` 4. | ||
4. `min_gas_amount` 3. | ||
|
||
3. `send_l1_to_l2` Emits the `L1ToL2Event` event upon completion of the check, which includes: | ||
1. `msg_sequence` | ||
2. `msg_sender | ||
3. `action` | ||
4. `min_gas_amount` | ||
5. `from`: the originator of `send_l1_to_l2`. In this case it is `l1_stub`. | ||
6. `gas_amount`: Base gas overhead on L2 based on `min_gas_amount` and estimated from `action` size. It is also the main basis for the amount of gas burned on L1. | ||
7. `L1ToL2Event_version`: event version number | ||
|
||
## L2 | ||
|
||
1. `rooch_node` listens to the `L1ToL2Event` event, parses its parameters, generates a proof of inclusion of the L1 event (that it happened on L1), and finally encapsulates it in an L2 tx. 2. | ||
2. pass the L2 tx to executor to validate the L1 event containment proof, executor will use the light node contract corresponding to L1 to validate the event containment proof. 3. after successful validation, execute `L1ToL2Event` event. | ||
3. execute `action` after successful verification. | ||
|
||
<img alt="L1 to L2 Messaging L2 Process" height="413" src="/docs/l1tol2_l2_process.jpeg" width="700"/> | ||
|
||
## Gas Fees | ||
|
||
Gas Fee is divided into two parts: | ||
|
||
1. L1 contract calling overhead | ||
2. L2 contract calling overhead (realized by L1 combustion) | ||
|
||
L1 contract call overhead accounts for most of the overall overhead, while L2 contract overhead is relatively small and has a certain free amount (for most of the asset transfer scenarios, the L2 free amount is more than enough). | ||
Anything above the free credit will be burned on L1 at a certain percentage: | ||
|
||
<img alt="Rooch L1ToL2 Gas Fee" height="450" src="/docs/l1tol2_gas_fee.jpeg" width="500"/> | ||
|
||
It's like a Gas Variable speed device, for different chains we just replace the L1 gear (adjust the L2:L1 gas ratio) to automate the combustion on the L1. This way, no matter which L1, the user only needs to be concerned about the overhead of the objective function on L2. | ||
and does not need to be concerned with the complexity of gas pricing. | ||
|
||
Burning will be implemented as a `while loop` in L1, with the following pseudo-code: | ||
|
||
``` | ||
i = 0 | ||
while (i < burn_amount) { | ||
i++ | ||
} | ||
``` | ||
|
||
## Security | ||
|
||
Rooch's L1 to L2 messaging mechanism guarantees that contract calls on L1 are correctly relayed to L2, and that the contract on L2 is responsible for checking the caller on L1 itself. | ||
This requires that the relevant `sender` information be encapsulated as a parameter to the `action` in `l1_stub.call_remote`. |
83 changes: 0 additions & 83 deletions
83
docs/website/pages/docs/tech-highlights/l1_to_l2_messaging.zh-CN.md
This file was deleted.
Oops, something went wrong.
78 changes: 78 additions & 0 deletions
78
docs/website/pages/docs/tech-highlights/l1_to_l2_messaging.zh-CN.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
# L1 至 L2 的消息传递 | ||
|
||
## 概述 | ||
|
||
L1 至 L2 的消息传递由 L1 触发的 L2 交易实现。(资产转移基于此机制) | ||
|
||
Rooch 具备多链资产结算的能力,对于每一条 L1 来说,其 L1 to L2 流程一致(注:合约名及其参数受不同智能合约语言影响在 L1 上略有不同),都是由 Rooch 上的轻节点验证来自 L1 的事件后执行 L2 交易: | ||
|
||
<img alt="L1 to L2 Messaging" height="400" src="/docs/l1tol2.jpeg" width="800"/> | ||
|
||
## L1 | ||
|
||
L1 需要对 L2 的调用生成相关事件,事件中包含了 L2 调用所需的所有信息以及发生在 L1 上的过程信息,这些信息将会被 `rooch_node` 解析并中继给 L2。 | ||
|
||
1. 用户通过调用 `l1_stub` 中的 `call_remote` 函数发起 L1 to L2 请求,所需参数包括: | ||
1. `action`: 编码后的 Rooch MoveAction | ||
2. `min_gas_amount`: L2 上允许使用的最小 gas 数量,即对调用 `action` 的估计值。 | ||
考虑到 L2 需要在调用 `action` 之前的处理开销,实际开销肯定会超过这个值。详见 [Gas Fees](#gas-fees)。 | ||
|
||
`l1_stub` 提供了较为友好的接口,调用者只需关心 L2 调用信息而无需关注信息封装和传递。 | ||
|
||
2. `l1_stub` 将调用 `rooch_transport` 的 `send_l1_to_l2` 函数完成 L1 上的事件记录和 gas 燃烧,参数包括: | ||
1. `msg_sequence` | ||
2. `msg_sender` | ||
3. `action` | ||
4. `min_gas_amount` | ||
|
||
3. `send_l1_to_l2` 在完成检查后,发出 `L1ToL2Event` 事件,其中包括: | ||
1. `msg_sequence` | ||
2. `msg_sender` | ||
3. `action` | ||
4. `min_gas_amount` | ||
5. `from`: `send_l1_to_l2` 的发起者。在这里是 `l1_stub`。 | ||
6. `gas_amount`: 基于 `min_gas_amount` 以及根据 `action` 尺寸估算得到的 L2 上的基础 gas 开销。也是 L1 上燃烧的 gas 数量主要依据。 | ||
7. `L1ToL2Event_version`: event 版本号 | ||
|
||
## L2 | ||
|
||
1. `rooch_node` 监听 `L1ToL2Event` 事件,解析其中的参数,生成 L1 事件包含证明(证明该事件在 L1 上发生),最终封装为 L2 tx | ||
2. 将 L2 tx 传递给 executor 验证 L1 事件包含证明,executor 将使用 L1 对应的轻节点合约验证事件的包含证明。 | ||
3. 验证成功后执行 `action` | ||
|
||
<img alt="L1 to L2 Messaging L2 Process" height="413" src="/docs/l1tol2_l2_process.jpeg" width="700"/> | ||
|
||
## Gas Fees | ||
|
||
Gas Fee 分为两个部分: | ||
|
||
1. L1 合约调用开销 | ||
2. L2 合约调用开销(由 L1 燃烧实现) | ||
|
||
其中 L1 合约开销占据整体开销的绝大部分,L2 合约开销相对较小且有一定的免费额度(对于绝大多数资产转移场景而言,L2 免费额度是绰绰有余的)。 | ||
对于超过免费额度的部分,将以一定比例在 L1 上燃烧: | ||
|
||
<img alt="Rooch L1ToL2 Gas Fee" height="450" src="/docs/l1tol2_gas_fee.jpeg" width="500"/> | ||
|
||
这就像是一个 Gas 变速装置,对于不同的链来说,我们只要替换 L1 的变速齿轮(调整 L2:L1 gas 比例)自动实现 L1 上的燃烧。这样无论是哪一条 L1, 使用者仅需要关注 L2 | ||
上目标函数的开销即可,无需关注复杂的 gas 定价。 | ||
|
||
燃烧将以在 L1 中以 `while loop` 形式实现,伪代码如下: | ||
|
||
``` | ||
i = 0 | ||
while (i < burn_amount) { | ||
i++ | ||
} | ||
``` | ||
|
||
## 安全性 | ||
|
||
Rooch 的 L1 to L2 消息机制保障的是 L1 上的合约调用能够被正确的中继到 L2 上,L2 上的合约自行负责对 L1 的调用者的检查,这要求 | ||
将相关的 `sender` 等信息作为参数封装进 `l1_stub.call_remote` 中的 `action`。 | ||
|
||
|
||
|
||
|
||
|
||
|
71 changes: 71 additions & 0 deletions
71
docs/website/pages/docs/tech-highlights/l2_to_l1_messaging.en-US.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
## L2 to L1 message passing | ||
|
||
## Overview | ||
|
||
L2 to L1 messaging is implemented by L1 transactions triggered by L2. (Asset transfers are based on this mechanism) | ||
|
||
Rooch has the ability of multi-chain asset settlement, for different roles of L1 (arbitration chain/settlement chain), the process is the same, both are: | ||
|
||
1. Initialization transaction: L2 to L1 request is initiated by user in L2. 2. Proof transaction: L2 to L1 request is initiated by user in L2. | ||
2. Proof transaction: the user submits a proof of inclusion of the transaction in L1, which proves the change of L2 state. 3. | ||
3. Confirmation Transaction: The user submits a transaction confirmation at L1, and L1 executes the L1 transaction requested by L2 after verification. | ||
|
||
The core difference between the arbitration/settlement chain in L2 to L1 messaging is the validation mechanism behind it: | ||
|
||
1. Arbitration chain: L2 is validated by the validation node directly through the arbitration contract on L1. 2. Settlement chain: L2 is validated by L2 through the arbitration contract on L1. | ||
2. Settlement Chain: L2 light node contracts assist the validating node to validate through the arbitration contract on L1. (See below for a more detailed description) | ||
|
||
## Initializing a transaction | ||
|
||
1. The user initiates the L2 to L1 request by calling the `call_remote` function in `l2_stub` with the following parameters. | ||
1. `action`: coded information about the contract call on L1 | ||
|
||
2. `l1_stub` will call the `send_l2_to_l1` function in `rooch_transport` to complete the logging of events on L2, with the following parameters: | ||
1. `msg_sequence | ||
2. `msg_sender | ||
3. `action` | ||
|
||
3. `send_l2_to_l1` After completing the check, issue the `L2ToL1Event` event with the following parameters: | ||
1. `msg_sequence | ||
2. `msg_sender | ||
3. `action` | ||
4. `from`: the originator of the `send_l2_to_l1`. In this case it is `l2_stub`. | ||
5. `L2ToL1Event_version`: event version number | ||
|
||
## Prove the transaction | ||
|
||
After the root of the L2 block containing the `L2ToL1Event` event has been committed to L1, the user can submit a proof transaction. | ||
|
||
### Proof generation | ||
|
||
This is a proof that the `L2ToL1Event` Merkle Trie contains a proof, there are multiple ways to generate it, we just need to make sure the root matches the record on L1. | ||
|
||
This is done off-chain. | ||
|
||
### Initiate a proof transaction | ||
|
||
Initiate a `prove_l2_to_l1` transaction on L1 via `rooch_transport` to verify that the proof we generated off-chain matches the L2 output of the record on L1. | ||
|
||
## Confirm Transaction | ||
|
||
At the end of the challenge period, users can submit confirmation transactions. | ||
|
||
A `finalize_l2_to_l1` transaction is initiated on L1 via `rooch_transport` to verify that the proof transaction passed the challenge period successfully. Upon completion of the check, `action` is invoked. | ||
|
||
## Settlement Chain Validation Mechanism | ||
|
||
Let's explore the nature of secure settlement by starting with Rollups' causality model, which is as follows for L2 to L1 messaging: | ||
|
||
1. cause: transaction on L2 | ||
2. effect: L2 output | ||
3. causal (message) medium: proposer | ||
4. observer: verifier | ||
|
||
For the arbitration chain, we already have a complete fraud proof mechanism, and causality does not rely on observers, so only an honest observer (verifier) is needed to guarantee that the causality has been correctly established. | ||
|
||
In order for the settlement chain to be equivalent to the arbitration chain, we need to construct consistent causality, which for the settlement chain implies the following preconditions: | ||
|
||
1. the same media completion result record: the proposer needs to record the L2 output in the settlement chain | ||
2. the same observer to verify the result record: through the L1 light node on the L2 to complete the L1 result record in the L2 confirmation, to realize the verifier's observation. | ||
|
||
Translated with www.DeepL.com/Translator (free version) |
70 changes: 70 additions & 0 deletions
70
docs/website/pages/docs/tech-highlights/l2_to_l1_messaging.zh-CN.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
# L2 至 L1 的消息传递 | ||
|
||
## 概述 | ||
|
||
L2 至 L1 的消息传递由 L2 触发的 L1 交易实现。(资产转移基于此机制) | ||
|
||
Rooch 具备多链资产结算的能力,对于不同角色的 L1 (仲裁链/结算链)来说,其流程一致,均为: | ||
|
||
1. 初始化交易:由用户在 L2 发起 L2 to L1 请求。 | ||
2. 证明交易:由用户在 L1 提交交易包含证明,证明 L2 状态的变更。 | ||
3. 确认交易:由用户在 L1 提交交易确认,L1 在验证后执行 L2 请求的 L1 交易。 | ||
|
||
仲裁链/结算链在 L2 至 L1 的消息传递中的核心区别在于背后的验证机制: | ||
|
||
1. 仲裁链:L2 由验证节点直接通过 L1 上的仲裁合约验证。 | ||
2. 结算链:由 L2 轻节点合约辅助验证节点通过 L1 上的仲裁合约验证。(更详细的说明见下文) | ||
|
||
## 初始化交易 | ||
|
||
1. 用户通过调用 `l2_stub` 中的 `call_remote` 函数发起 L2 to L1 请求,所需参数包括: | ||
1. `action`: 编码后的 L1 上的合约调用信息 | ||
|
||
2. `l1_stub` 将调用 `rooch_transport` 的 `send_l2_to_l1` 函数完成 L2 上的事件记录,参数包括: | ||
1. `msg_sequence` | ||
2. `msg_sender` | ||
3. `action` | ||
|
||
3. `send_l2_to_l1` 在完成检查后,发出 `L2ToL1Event` 事件,其中包括: | ||
1. `msg_sequence` | ||
2. `msg_sender` | ||
3. `action` | ||
4. `from`: `send_l2_to_l1` 的 发起者。在这里是 `l2_stub`。 | ||
5. `L2ToL1Event_version`: event 版本号 | ||
|
||
## 证明交易 | ||
|
||
在包含 `L2ToL1Event` 事件的 L2 区块的根被提交到 L1 后,用户可提交证明交易。 | ||
|
||
### 证明生成 | ||
|
||
这是一个关于 `L2ToL1Event` Merkle Trie 包含证明,生成它有多种方式,我们只需要保证其根与 L1 上记录相匹配即可。 | ||
|
||
此工作在链下完成。 | ||
|
||
### 发起证明交易 | ||
|
||
在 L1 上通过 `rooch_transport` 发起 `prove_l2_to_l1` 交易以验证我们在链下生成的证明是否与 L1 上的记录的 L2 output 相匹配。 | ||
|
||
## 确认交易 | ||
|
||
在挑战期结束后,用户可提交确认交易。 | ||
|
||
在 L1 上通过 `rooch_transport` 发起 `finalize_l2_to_l1` 交易以验证证明交易顺利通过了挑战期。在检查完成后,将调用 `action`。 | ||
|
||
## 结算链验证机制 | ||
|
||
让我们先从 Rollups 的因果关系模型出发来探索安全结算本质,对于 L2 至 L1 的消息传递,其模型如下: | ||
|
||
1. 因: L2 上交易 | ||
2. 果:L2 output | ||
3. 因果(消息)媒介:proposer | ||
4. 观察者: verifier | ||
|
||
对于仲裁链,我们已有完整的欺诈证明机制,而因果关系不依赖观察者,因此只需要一个诚实的观察者(verifier)即可保障因果关系已被正确建立。 | ||
|
||
为让结算链与仲裁链等效,我们需要构建一致的因果关系,对于结算链,则意味着如下前置条件: | ||
|
||
1. 相同媒介完成结果记录:proposer 需要在结算链上记录 L2 output | ||
2. 相同的观察者验证结果记录:通过 L2 上的 L1 轻节点完成 L1 结果记录在 L2 的确认,实现 verifier 的观察。 | ||
|
Oops, something went wrong.