Skip to content

Commit 064ee41

Browse files
authored
v0.14.0 messaging (#1634)
* init * merge fixes * minor fix * minor fixes
1 parent e0e5949 commit 064ee41

File tree

3 files changed

+73
-85
lines changed

3 files changed

+73
-85
lines changed

components/Starknet/modules/architecture/nav.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
** xref:cryptography.adoc[Cryptography]
66
** xref:data-availability.adoc[Data availability]
77
** xref:fees.adoc[Fees]
8-
** xref:messaging.adoc[L1-L2 messaging]
8+
** xref:messaging.adoc[L1L2 messaging]
99
** xref:staking.adoc[Staking]
1010
** xref:state.adoc[State]
1111
** xref:strk.adoc[STRK]
Lines changed: 71 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,27 @@
1-
[id="messaging_mechanism"]
2-
= L1-L2 messaging mechanism
1+
= L1 <-> L2 messaging
32

4-
Starknet's ability to interact with L1 is crucial. _Messaging_ is the mechanism that enables this interaction.
3+
== Overview
4+
Starknet's ability to interact with L1 is crucial, and is used by bridges (e.g., for depositing your tokens in the L1 bridge contract, and automatically triggers the minting of the same token on L2), link:https://starkware.co/resource/defi-pooling/[DeFi pooling^] and https://www.starknet.io/en/ecosystem/dapps[more^]. Messaging — both xref:l2_l1_messages[from L1 to L2] and from xref:l1_l2_message_protocol[L2 to L1] — is the mechanism that enables this interaction.
55

6-
For example, you can perform computations on L2 and use the result on L1.
7-
8-
Bridges on Starknet use the L1-L2 messaging mechanism. Consider that you want to bridge tokens from Ethereum to Starknet. You deposit your tokens in the L1 bridge contract, which automatically triggers the minting of the same token on L2. Another good use case for L1-L2 messaging is Defi pooling. For more information, see link:https://starkware.co/resource/defi-pooling/[DeFi pooling] on StarkWare's site and link:https://www.starknet.io/en/ecosystem/dapps[dApps] on https://www.starknet.io.
9-
10-
Be aware that the messaging mechanism is _asynchronous_ and _asymmetric_.
6+
[IMPORTANT]
7+
====
8+
Starknet's messaging mechanism is both _asynchronous_ and _asymmetric_.
119
1210
* _Asynchronous_: Your contract code, whether Cairo or Solidity, cannot await the result of the message being sent on the other layer within your contract code's execution.
1311
* _Asymmetric_: Sending a message from Ethereum to Starknet, L1->L2, is fully automated by the Starknet sequencer, so the message is automatically delivered to the target contract on L2. However, when sending a message from Starknet to Ethereum, L2->L1, the sequencer only sends the hash of the message. You must then consume the message manually using a transaction on L1.
12+
====
13+
14+
.Additional resources
15+
16+
* https://book.cairo-lang.org/appendix-08-system-calls.html#send_message_to_l1[The `send_message_to_L1` syscall^]
17+
* https://github.com/starkware-libs/cairo-lang/blob/54d7e92a703b3b5a1e07e9389608178129946efc/src/starkware/starknet/solidity/IStarknetMessaging.sol#L13[The Starknet Core contract's `sendMessageToL2` function^]
18+
* https://book.cairo-lang.org/ch16-04-L1-L2-messaging.html[L1-L2 Messaging in the Cairo Book^]
1419

15-
[id="l2-l1_messages"]
1620
== L2 -> L1 messages
1721

18-
Contracts on L2 can interact asynchronously with contracts on L1 using the L2->L1 messaging protocol.
22+
=== L2 -> L1 message protocol
1923

20-
The protocol consists of the following stages:
24+
The L2 -> L1 message protocol consists of the following stages:
2125

2226
. During the execution of a transaction, a contract on Starknet sends a message from L2 to L1 by calling the `send_message_to_L1` syscall.
2327
. The sequencer attaches the message parameters to the block that includes the syscall invocation. The message parameters include the address of the sender on L2, the address of the recipient contract on L1, and the message data.
@@ -44,27 +48,21 @@ This function, which is part of the Starknet Core Contract, verifies the followi
4448
* The hashes of the L2 sent message parameters, now stored on the Core Contract, and the L1 received message parameters, are the same.
4549
* The entity calling the function is indeed the recipient on L1.
4650
+
47-
// We need to separate out these functions into a reference.
4851
In such a case, the counter corresponding to the message hash in the Starknet Core Contract decreases by one. For more information, see the link:https://github.com/starkware-libs/cairo-lang/blob/4e233516f52477ad158bc81a86ec2760471c1b65/src/starkware/starknet/eth/StarknetMessaging.sol#L130C7-L130C7#[`consumeMessageFromL2`] function in `StarknetMessaging.sol`.
4952

50-
xref:#diagram_l2-l1_messaging_mechanism[] illustrates this flow:
53+
The protocol is summarized in the following illustration:
5154

52-
[#diagram_l2-l1_messaging_mechanism]
53-
.L2->L1 Messaging mechanism
5455
image::l2l1.png[L2->L1 message mechanism]
5556

5657
=== L2 -> L1 message structure
5758

58-
// xref:#structure_l2-l1[] illustrates the structure of an L2 -> L1 message.
59-
60-
The structure of an L2 -> L1 message is described as follows under `MSG_TO_L1` in the link:https://github.com/starkware-libs/starknet-specs/blob/master/api/starknet_api_openrpc.json[Starknet API JSON RPC] specification:
59+
The structure of an L2 -> L1 message is defined under `MSG_TO_L1` in the https://github.com/starkware-libs/starknet-specs/blob/master/api/starknet_api_openrpc.json[Starknet API JSON RPC^] specification as follows:
6160

62-
[horizontal,labelwidth="30",role="stripes-odd"]
61+
[horizontal,labelwidth="30"]
6362
`from_address` (`felt252`):: The address of the L2 contract sending the message.
6463
`to_address` (`EthAddress`):: The target L1 address the message is sent to.
65-
`payload` (`Array<felt252>`) :: The payload of the message.
64+
`payload` (`Array<felt252>`):: The payload of the message.
6665

67-
[#hashing_l2-l1]
6866
=== L2 -> L1 message hashing
6967

7068
The hash of an L2 -> L1 message is computed on L1 as follows:
@@ -86,12 +84,11 @@ keccak256(
8684
Sending an L2 to L1 message always incurs a fixed cost of 20,000 L1 gas, because the hash of the message being sent must be written to L1 storage in the Starknet Core Contract.
8785
====
8886

89-
[id="l1-l2-messages"]
9087
== L1 -> L2 messages
9188

92-
Contracts on L1 can interact asynchronously with contracts on L2 using the _L1->L2_ messaging protocol.
89+
=== L1 -> L2 message protocol
9390

94-
The protocol consists of the following stages:
91+
The L1 -> L2 message protocol consists of the following stages:
9592

9693
. An L1 contract induces a message to an L2 contract on Starknet by calling the link:https://github.com/starkware-libs/cairo-lang/blob/54d7e92a703b3b5a1e07e9389608178129946efc/src/starkware/starknet/solidity/IStarknetMessaging.sol#L13[`sendMessageToL2`] function on the Starknet Core Contract with the message parameters.
9794
+
@@ -108,11 +105,6 @@ The Starknet Core Contract hashes the message parameters and updates the L1->L2
108105

109106
At this point, the message is handled.
110107

111-
// The above flow is illustrated in the following diagram:
112-
// #THIS IMAGE IS WRONG & MISLEADING#
113-
114-
// image::l1l2.png[l1l2]
115-
116108
An L1->L2 message consists of the following:
117109

118110
* L1 sender's address
@@ -128,7 +120,37 @@ The message nonce is maintained on the Starknet Core Contract on L1, and is incr
128120
For more information, see xref:#l1_l2_message_structure[L1->L2 structure].
129121
====
130122

131-
[id="l2-l1_message_cancellation"]
123+
=== L1 -> L2 message structure
124+
125+
126+
For completeness, the following table describes the precise structure of both the message as it appears on L1 and the induced transaction as it appears on L2:
127+
128+
[%autowidth.stretch]
129+
|===
130+
| FromAddress | ToAddress | Selector | Payload | Nonce |
131+
132+
| `EthereumAddress` | `FieldElement` | `FieldElement` | `List+++<FieldElement>+++` | `FieldElement` |
133+
|===
134+
135+
=== L1 -> L2 message hashing
136+
137+
The hash of the message is computed on L1 as follows:
138+
139+
[source,js]
140+
----
141+
keccak256(
142+
abi.encodePacked(
143+
uint256(FromAddress),
144+
ToAddress,
145+
Nonce,
146+
Selector,
147+
Payload.length,
148+
Payload
149+
)
150+
);
151+
----
152+
153+
132154
=== L1 -> L2 message cancellation
133155

134156
[NOTE]
@@ -148,7 +170,6 @@ The steps in this flow are as follows:
148170

149171

150172

151-
[id="l1-l2-message-fees"]
152173
=== L1 -> L2 message fees
153174

154175
An L1 -> L2 message induces a transaction on L2, which, unlike regular transactions, is not sent by an account. This calls for a different mechanism for paying the transaction's fee, for otherwise the sequencer has no incentive of including L1 handler transactions inside a block.
@@ -160,60 +181,34 @@ The sequencer takes this fee in exchange for handling the message. The sequencer
160181
The fee itself is calculated in the xref:architecture:fees.adoc#overall_fee[same manner] as
161182
"regular" L2 transactions.
162183

163-
[id="structure_and_hashing_l1-l2"]
164-
[#l1_l2_message_structure]
165-
=== L1 -> L2 structure
166-
167-
For completeness, xref:#l1_l2_message_structure[] describes the precise structure of both the message as it appears on L1 and the induced transaction as it appears on L2.
168-
169-
[#L1-L2_message_structure]
170-
.L1 -> L2 message structure
171-
[%autowidth.stretch]
172-
|===
173-
| FromAddress | ToAddress | Selector | Payload | Nonce |
174-
175-
| `EthereumAddress` | `FieldElement` | `FieldElement` | `List+++<FieldElement>+++` | `FieldElement` |
176-
|===
177-
178-
[#hashing_l1-l2]
179-
=== L1 -> L2 hashing
180-
181-
The hash of the message is computed on L1 as follows:
182-
183-
[source,js]
184-
----
185-
keccak256(
186-
abi.encodePacked(
187-
uint256(FromAddress),
188-
ToAddress,
189-
Nonce,
190-
Selector,
191-
Payload.length,
192-
Payload
193-
)
194-
);
195-
----
196-
197-
[id="l1_handler_transaction"]
198184
=== L1 handler transaction
199185

186+
==== Transaction fields
187+
200188
[%autowidth.stretch]
201189
|===
202190
| Version | ContractAddress | Selector | Calldata | Nonce |
203191

204192
| `FieldElement` | `FieldElement` | `FieldElement` | `List+++<FieldElement>+++` | `FieldElement` |
205193
|===
206194

195+
[NOTE]
196+
====
197+
In an L1 handler transaction, the first element of the calldata is always the sender's Ethereum address.
198+
====
199+
200+
==== Hash calculation
201+
207202
The hash of the corresponding L1 handler transaction on L2 is computed as follows:
208203

209204
[source,cairo]
210205
----
211-
l1_handler_tx_hash = _h_(
206+
l1_handler_tx_hash = h(
212207
"l1_handler",
213208
version,
214209
contract_address,
215210
entry_point_selector,
216-
_h_(calldata),
211+
h(calldata),
217212
0,
218213
chain_id,
219214
nonce
@@ -228,26 +223,19 @@ Where:
228223
* _h_ is the xref:architecture:cryptography.adoc#hash-functions#pedersen_hash[Pedersen] hash (note that since we're hashing an array, the # of inputs needs to be appended to the hash).
229224
* `0` indicates that L1 to L2 message fees are charged on L1.
230225

231-
[NOTE]
232-
====
233-
In an L1 handler transaction, the first element of the calldata is always the sender's Ethereum address.
234-
====
226+
==== Caveats and limitations
235227

236-
[NOTE]
237-
====
238-
Since L1 handler transactions are not initiated by an account, invoking link:https://github.com/starkware-libs/cairo/blob/2203a47f8a098cd4718d03bd109ca014049419e7/corelib/src/starknet/info.cairo#L49[`get_caller_address()`] or similar account-related functions returns the address `0x0`.
239-
====
228+
* Since L1 handler transactions are not initiated by an account, invoking https://github.com/starkware-libs/cairo/blob/2203a47f8a098cd4718d03bd109ca014049419e7/corelib/src/starknet/info.cairo#L49[`get_caller_address`^] or similar account-related functions returns the address `0x0`.
229+
* Starting from Starknet version 0.14.0:
230+
** L1 handlers that fail execution will appear in a block as `REVERTED`, instead of only be written in the feeder gateway's database as `REJECTED`. The purpose of this change is to simplify the tracking of messages L1 -> L2, and the implementation of `getMessageStatus` in particular.
231+
** The `l1_gas`, `l2_gas`, and `l1_data_gas` execution resources of L1 handlers will be bounded as follows:
232+
*** `l2_gas` will bounded by stem:[10^8] (the same as ``++__validate__++``'s)
233+
*** `l1_gas` and `l1_data_gas` will be bounded by stem:[4*10^4] and stem:[2*10^4], respectively (to allow for sending one L2 -> L1 message)
240234

241-
.Supported versions of the `L1HandlerTransaction` transaction type
235+
==== Supported versions
242236
[cols=",,",]
243237
|===
244238
|Current version |Deprecated versions | Unsupported versions
245239

246240
| v0 | N/A | N/A
247241
|===
248-
249-
== Additional resources
250-
251-
* https://book.cairo-lang.org/appendix-08-system-calls.html#send_message_to_l1[`send_message_to_L1`^] syscall
252-
* link:https://github.com/starkware-libs/cairo-lang/blob/54d7e92a703b3b5a1e07e9389608178129946efc/src/starkware/starknet/solidity/IStarknetMessaging.sol#L13[`sendMessageToL2`] function on the Starknet Core Contract
253-
* For more information on how messaging works within the Starknet Core Contract, including details on coding, see link:https://book.cairo-lang.org/ch16-04-L1-L2-messaging.html[L1-L2 Messaging] in _The Cairo Book: The Cairo Programming Language_

components/Starknet/modules/architecture/pages/os.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ Contract calls are in fact done non-deterministically, i.e. the contract's respo
4343

4444
* State updates are accumulated in the global state updates dictionary
4545
. Verifying that the new commitment corresponds to applying the updates accumulated in the global state updates dictionary to the old commitment (for more details, see the link:https://github.com/starkware-libs/cairo-lang/blob/8e11b8cc65ae1d0959328b1b4a40b92df8b58595/src/starkware/starknet/core/os/state/state.cairo#L40[`state_update` function in `state.cairo`^]).
46-
. Encoding the state diff and adding it to the output segment for xref:network-architecture/data-availability.adoc[data availability] purposes (for more details, see the link:https://github.com/starkware-libs/cairo-lang/blob/8e11b8cc65ae1d0959328b1b4a40b92df8b58595/src/starkware/starknet/core/os/output.cairo#L71[`serialize_os_output` function in `output.cairo`^])
46+
. Encoding the state diff and adding it to the output segment for xref:data-availability.adoc[data availability] purposes (for more details, see the link:https://github.com/starkware-libs/cairo-lang/blob/8e11b8cc65ae1d0959328b1b4a40b92df8b58595/src/starkware/starknet/core/os/output.cairo#L71[`serialize_os_output` function in `output.cairo`^])
4747

4848
[id="syscall-mechanism"]
4949
=== Syscall mechanism

0 commit comments

Comments
 (0)