From fe6e6e7c6c294249155bd83f313b99d0219f00b4 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Thu, 20 Jan 2022 19:44:30 +0100 Subject: [PATCH 01/12] add new terms to glossary, fixing internal links but not yet external links --- specs/glossary.md | 215 +++++++++++++++++++++++++++++----------------- 1 file changed, 134 insertions(+), 81 deletions(-) diff --git a/specs/glossary.md b/specs/glossary.md index 98ea789e..17bbc188 100644 --- a/specs/glossary.md +++ b/specs/glossary.md @@ -13,7 +13,17 @@ - [Receipt](#receipt) - [Transaction Type](#transaction-type) - [Fork Choice Rule](#fork-choice-rule) -- [L2 Chain Concepts](#l2-chain-concepts) +- [Deposits](#deposits) + - [Deposited Transaction](#deposited-transaction) + - [Deposit Block](#deposit-block) + - [L1 Attributes Deposited Transaction](#l1-attributes-deposited-transaction) + - [User-Deposited Transaction](#user-deposited-transaction) + - [Depositing Call](#depositing-call) + - [Depositing Transaction](#depositing-transaction) + - [Depositor](#depositor) + - [Deposited Transaction Type](#deposited-transaction-type) + - [Deposit Contract](#deposit-contract) +- [Other L2 Chain Concepts](#other-l2-chain-concepts) - [Address Aliasing](#address-aliasing) - [L2 Chain Inception](#l2-chain-inception) - [Rollup Node](#rollup-node) @@ -21,15 +31,12 @@ - [L2 Chain Derivation](#l2-chain-derivation) - [L2 Derivation Inputs](#l2-derivation-inputs) - [Payload Attributes](#payload-attributes) - - [Deposits](#deposits) - - [L1 Attributes Deposit](#l1-attributes-deposit) - - [Transaction Deposit](#transaction-deposit) - [L1 Attributes Predeployed Contract](#l1-attributes-predeployed-contract) - - [Deposit Transaction Type](#deposit-transaction-type) - - [Deposit Feed Contract](#deposit-feed-contract) - [Execution Engine Concepts](#execution-engine-concepts) - [Execution Engine](#execution-engine) +------------------------------------------------------------------------------------------------------------------------ + # General Terms ## Layer 1 (L1) @@ -129,7 +136,124 @@ on-chain-confirmed head, or the on-chain-finalized head. ------------------------------------------------------------------------------------------------------------------------ -# L2 Chain Concepts +# Deposits + +[deposits]: glossary.md#deposits + +In general, a deposit is an L2 transaction derived from an L1 block (by the [rollup driver]). + +While transaction deposits are notably (but not only) used to "deposit" (bridge) ETH and tokens to L2, the word +*deposit* should be understood as "a transaction *deposited* to L2 from L1". + +This term *deposit* is somewhat ambiguous as these "transactions" exist at multiple levels. This section disambiguates all +deposit-related terms. + +Notably, a *deposit* can refer to: + +- A [deposited transaction][deposited] (on L2) that is part of a [deposite block][deposit-block]. +- A [depositing call][depositing-call] that causes a [deposited transaction][deposited] to be derived. +- The event/log data generated by the [depositing call][depositing-call], which is what the [rollup driver] reads to + derive the [deposited transaction][deposited]. + +We sometimes also talk about *user deposit* which is a similar term that explicitly excludes [L1 attributes deposited +transactions][l1-attr-deposit]. + +Deposits are specified in the [deposits specification][deposits-spec]. + +[deposits-spec]: deposits.md + +## Deposited Transaction + +[deposited]: glossary.md#deposited-transaction + +A *deposited transaction* is a L2 transaction that was derived from L1 and is included in a [deposit +block][deposit-block]. + +There are two kinds of deposited transactions: + +- [L1 attributes deposited transaction][l1-attr-deposit], which submits the L1 block's attributes to the [L1 Attributes + Predeployed Contract][l1-attr-predeploy]. +- [User-deposited transactions][user-deposited], which are transactions derived from an L1 call to the [deposit + contract][deposit-contract]. + +[deposits-spec]: deposits.md + +## Deposit Block + +[deposit-block]: glossary.md#deposit-block + +A *deposit block* is a L2 block that contains only [deposited transactions][deposited]. + +## L1 Attributes Deposited Transaction + +[l1-attr-deposit]: glossary.md#l1-attributes-deposited-transaction + +An *L1 attributes deposited transaction* is [deposited transaction][deposited] that is used to register the L1 block +attributes (number, timestamp, ...) on L2 via a call to the [L1 Attributes Predeployed Contract][l1-attr-predeploy]. +That contract can then be used to read the the attributes of the L1 block corresponding to the current L2 block. + +L1 attributes deposited transactions are specified in the [L1 Attributes Deposit][l1-attributes-tx-spec] section of the +deposits specification. + +[l1-attributes-tx-spec]: deposits.md#l1-attributes-deposit + +## User-Deposited Transaction + +[user-deposited]: glossary.md#user-deposited-transaction + +A *user-deposited transaction* is a [deposited transaction][deposited] which is derived from an L1 call to the [deposit + contract][deposit-contract] (a [depositing call][depositing-call]). + +User-deposited transactions are specified in the [Transaction Deposits][tx-deposits-spec] section of the deposits +specification. + +[tx-deposits-spec]: deposits.md##l1-transaction-deposits + +## Depositing Call + +[depositing-call]: glossary.md#depositing-call + +A *depositing call* is an L1 call to the [deposit contract][deposit-contract], which will be derived to a +[user-deposited transaction][user-deposited] by the [rollup driver]. + +This call specifies all the data (destination, value, calldata, ...) for the deposited transaction. "submits* + +## Depositing Transaction + +[depositing-tx]: glossary.md#depositing-transaction + +A *depositing transaction* is an L1 transaction that makes one or more [depositing calls][depositing-call]. + +## Depositor + +[depositor]: glossary.md#depositor + +The *depositor* is the L1 account (contract or [EOA]) that makes (is the `msg.sender` of) the [depositing +call][depositing-call]. The *depositor* is **NOT** the originator of the depositing transaction (i.e. `tx.origin`). + +## Deposited Transaction Type + +[deposit-tx-type]: glossary.md#deposited-transaction-type + +The *deposited transaction type* is an [EIP-2718] [transaction type][transaction-type], which specifies the input fields +and correct handling of a [deposited transaction][deposited]. + +## Deposit Contract + +[deposit-contract]: glossary.md#deposit-contract + +The *deposit contract* is qn [L1] contract to which [EOAs][EOA] and contracts may send [deposits]. The deposits are +emitted as log records (in Solidity, these are called *events*) for consumption by [rollup nodes][rollup node]. + +Advanced note: the deposits are not stored in calldata because they can be sent by contracts, in which case the calldata +is part of the execution, but its value is not captured in one of the [Merkle roots][Merkle root] included in the L1 +block. + +cf. [Deposits Specification](deposits.md) + +------------------------------------------------------------------------------------------------------------------------ + +# Other L2 Chain Concepts ## Address Aliasing @@ -177,13 +301,13 @@ Specification)](rollup-node.md#l2-chain-derivation) This term refers to data that is found in L1 blocks and is read by the [rollup node] to construct [payload attributes]. -Chain derivation attributes include: +L2 derivation inputs include: - L1 block attributes - block number - timestamp - basefee -- [deposits] +- [deposits] (as log data) ## Payload Attributes @@ -200,57 +324,6 @@ cf. [Execution Engine Specification](exec-engine.md) Payload attributes were historically called "L2 block inputs" in the L2 spec and you might still hear some people using this term. -## Deposits - -[deposits]: glossary.md#deposits - -A deposit is an L2 transaction derived from an L1 block. - -There are two kinds of deposits: - -- [L1 Attributes Deposit][l1-attributes-deposit], which submits the L1 block's attributes to the [L1 Attributes - Predeployed Contract][l1-attr-predeploy]. -- [Transaction Deposits][tx-deposits], which are transaction that have been submitted on L1, via a transaction sent to -the [deposit feed contract][deposit-feed]. - -While transaction deposits are notably (but not only) used to "deposit" (bridge) ETH and tokens to L2, the word -*deposit* should be understood as "a transaction *deposited* to L2 from L1". - -The term *deposit* performs the double duty of referring to both: - -1. The transaction information submitted on L1 to the [deposit feed contract][deposit-feed]. This is a kind of [L2 - derivation input][deriv-inputs]. -2. The actual L2 transaction derived from this L1 input. - -Deposits are specified in the [deposits specification][deposits-spec]. - -[deposits-spec]: deposits.md - -## L1 Attributes Deposit - -[l1-attributes-deposit]: glossary.md#l1-attributes-deposit - -A [deposit][deposits] that is used to register the L1 block attributes (number, timestamp, ...) on L2 via a call to the -[L1 Attributes Predeployed Contract][l1-attr-predeploy]. That contract can then be used to read the the attributes of -the L1 block corresponding to the current L2 block. - -L1 attributes deposits are specified in the [L1 Attributes Deposit][l1-attributes-tx-spec] section of the deposits -specification. - -[l1-attributes-tx-spec]: deposits.md#l1-attributes-deposit - -## Transaction Deposits - -[tx-deposits]: #transaction-deposits - -These [deposits] are transaction that have been submitted on L1, via a transaction sent to the [deposit feed -contract][deposit-feed]. - -Transaction deposits are specified in the [Transaction Deposits][tx-deposits-spec] section of the deposits -specification. - -[tx-deposits-spec]: deposits.md#l1-transaction-deposits - ## L1 Attributes Predeployed Contract [l1-attr-predeploy]: glossary.md#l1-attributes-predeployed-contract @@ -258,27 +331,7 @@ specification. A [predeployed contract][predeploy] on L2 that can be used to retrieve the L1 block attributes of L1 blocks with a given block number or a given block hash. -cf. [L1 Attributes Predeployed Contract Specification](#l1-attributes--reference-implementation) - -## Deposit Transaction Type - -[deposit-tx-type]: glossary.md#deposit-transaction-type - -The deposit transaction type is an [EIP-2718] [transaction type][transaction-type], which specifies -the input fields and correct handling of a [deposit][deposits]. - -## Deposit Feed Contract - -[deposit-feed]: glossary.md#deposit-feed-contract - -An [L1] contract to which [EOAs][EOA] and contracts may send [deposits]. The deposits are emitted as log records (in -Solidity, these are called *events*) for consumption by [rollup nodes][rollup node]. - -Advanced note: the deposits are not stored in calldata because they can be send by contracts, in which case the calldata -is part of the execution, but its value is not captured in one of the [Merkle roots][Merkle root] included in the L1 -block. - -cf. [Deposits Specification](deposits.md) +cf. [L1 Attributes Predeployed Contract Specification](deposits.md#l1-attributes--reference-implementation) ------------------------------------------------------------------------------------------------------------------------ From 449d02ee1aa8c0da879f0d374b0e4f2f126037f7 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Thu, 20 Jan 2022 19:57:26 +0100 Subject: [PATCH 02/12] add table of contents to deposit spec --- specs/deposits.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/specs/deposits.md b/specs/deposits.md index 175ba5bd..d1117e11 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -12,6 +12,24 @@ new [transaction type][transaction-type] for deposits. It also describes how deposits are initiated on L1, along with the authorization and validation conditions on L2. +## Table of Contents + +- [The Deposit Transaction Type](#the-deposit-transaction-type) + - [Uses of the Deposit Transaction Type](#uses-of-the-deposit-transaction-type) + - [Validation and Authorization of Deposit Transaction + Types](#validation-and-authorization-of-deposit-transaction-types) + - [Execution](#execution) + - [Nonce Handling](#nonce-handling) +- [L1 Attributes Deposits](#l1-attributes-deposit) +- [Special Accounts on L2](#special-accounts-on-l2) + - [L1 Attributes Depositor Account](l1-attributes-depositor-account) + - [L1 Attributes Predeploy](#l1-attributes-predeploy) + - [L1 Attributes: Reference Implementation](#l1-attributes--reference-implementation) +- [L1 Transaction Deposits](#l1-transaction-deposits) + - [Deposit Feed Contract](#deposit-feed-contract) + - [Address Aliasing](#address-aliasing) + - [Deposit Feed: Reference Implementation](#deposit-feed--reference-implementation) + ## The Deposit Transaction Type [deposit-transaction-type]: #the-deposit-transaction-type @@ -201,7 +219,7 @@ The deposit feed handles two special cases: > **TODO** Define if/how ETH withdrawals occur. -#### Address aliasing +#### Address Aliasing [address-aliasing]: #address-aliasing From ed90cf1a85c6b421099aa49f0bbb5b17bdfd448f Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Fri, 21 Jan 2022 01:54:56 +0100 Subject: [PATCH 03/12] update deposits.md to use standardized terms --- specs/deposits.md | 143 +++++++++++++++++++++++----------------------- specs/glossary.md | 6 +- 2 files changed, 75 insertions(+), 74 deletions(-) diff --git a/specs/deposits.md b/specs/deposits.md index d1117e11..f675fcdc 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -4,40 +4,48 @@ [transaction-type]: glossary.md#transaction-type [derivation]: glossary.md#L2-chain-derivation [execution-engine]: glossary.md#execution-engine +[deposited]: glossary.md#deposited [deposits]: glossary.md#deposits -[L1 attributes deposit]: glossary.md#l1-attributes-deposit -[transaction deposits]: glossary.md#transaction-deposits +[g-l1-attr-deposit]: glossary.md#l1-attributes-deposited-transaction +[g-user-deposited]: glossary.md#user-deposited-transaction +[g-deposit-block]: glossary.md#deposit-block +[g-eoa]: glossary.md#eoa -[Deposits] are transactions which are initiated on L1, and executed on L2. This document outlines a -new [transaction type][transaction-type] for deposits. It also describes how deposits are initiated -on L1, along with the authorization and validation conditions on L2. +[Deposited transactions], also known as [deposits] are transactions which are initiated on L1, and +executed on L2. This document outlines a new [transaction type][transaction-type] for deposits. It +also describes how deposits are initiated on L1, along with the authorization and validation +conditions on L2. + +**Vocabulary note**: *deposited transaction* refers specifically to an L2 transaction, while +*deposit* can refer to the transaction at various stages (for instance when it is deposited on L1). ## Table of Contents -- [The Deposit Transaction Type](#the-deposit-transaction-type) - - [Uses of the Deposit Transaction Type](#uses-of-the-deposit-transaction-type) - - [Validation and Authorization of Deposit Transaction - Types](#validation-and-authorization-of-deposit-transaction-types) +- [The Deposited Transaction Type](#the-deposited-transaction-type) + - [Kinds of Deposited Transactions](#kinds-of-deposited-transactions) + - [Validation and Authorization of Deposited + Transaction](#validation-and-authorization-of-deposit-transaction-types) - [Execution](#execution) - [Nonce Handling](#nonce-handling) -- [L1 Attributes Deposits](#l1-attributes-deposit) +- [L1 Attributes Deposited Transaction](#l1-attributes-deposited-transaction) - [Special Accounts on L2](#special-accounts-on-l2) - - [L1 Attributes Depositor Account](l1-attributes-depositor-account) - - [L1 Attributes Predeploy](#l1-attributes-predeploy) - - [L1 Attributes: Reference Implementation](#l1-attributes--reference-implementation) -- [L1 Transaction Deposits](#l1-transaction-deposits) + - [L1 Attributes Depositor Account](#l1-attributes-depositor-account) + - [L1 Attributes Predeployed Contract](#l1-attributes-predeployed-contract) + - [L1 Attributes Predeployed Contract: Reference Implementation](#l1-attributes-predeployed-contract--reference-implementation) +- [User-Deposited Transactions](#user-deposited-transactions) - [Deposit Feed Contract](#deposit-feed-contract) - [Address Aliasing](#address-aliasing) - - [Deposit Feed: Reference Implementation](#deposit-feed--reference-implementation) + - [Deposit Feed Contract: Reference Implementation](#deposit-feed-contract--reference-implementation) -## The Deposit Transaction Type +## The Deposited Transaction Type -[deposit-transaction-type]: #the-deposit-transaction-type +[deposited-tx-type]: #the-deposited-transaction-type -Deposit transactions have the following notable distinctions from existing transaction types: +[Deposited transactions][deposited] have the following notable distinctions from existing +transaction types: 1. They are derived from Layer 1 blocks, and must be included as part of the protocol. -2. They do not include signature validation (see [L1 transaction deposits][l1-transaction-deposits] +2. They do not include signature validation (see [User-Deposited Transactions][user-deposited] for the rationale). We define a new [EIP-2718] compatible transaction type with the prefix `0x7E`, and the following @@ -62,41 +70,36 @@ Picking a high identifier minimizes the risk that the identifier will be used be transaction type on the L1 chain in the future. We don't pick `0x7F` itself in case it becomes used for a variable-length encoding scheme. -### Uses of the Deposit Transaction Type - -Although in practice we define only one new transaction type we can distinguish between two distinct -situations which occur in the deposit block, based on their positioning. +### Kinds of Deposited Transactions -1. The first transaction MUST be a [L1 attributes deposit][l1-attributes-deposit], followed by -2. an array of zero-or-more [L1 transaction deposits][l1-transaction-deposits] submitted to the -deposit feed contract on L1. +Although we define only one new transaction type, we can distinguish between two kinds of deposited +transactions, based on their positioning in the [deposit block][g-deposit-block]: -The rationale for creating only one new transaction type is to minimize both -modifications to L1 client software and complexity in general. +1. The first transaction MUST be a [L1 attributes deposited transaction][l1-attr-deposit], followed + by +2. an array of zero-or-more [user-deposited transactions][user-deposited] submitted to the deposit + feed contract on L1. -> **TODO** Specify and link to deposit blocks +We only define a single new transaction type in order to minimize modifications to L1 client +software, and complexity in general. -### Validation and Authorization of Deposit Transaction Types +### Validation and Authorization of Deposited Transactions -[authorization]: #validation-and-authorization-of-deposit-transaction-types +[authorization]: #validation-and-authorization-of-deposited-transaction -As noted above, the deposit transaction type does not include a signature for validation. Rather, -authorization is handled by the [L2 chain Derivation][derivation] process, which when correctly -processed will only derive transactions with a `from` address attested to by the logs of the [L1 +As noted above, the deposited transaction type does not include a signature for validation. Rather, +authorization is handled by the [L2 chain derivation][derivation] process, which when correctly +applied will only derive transactions with a `from` address attested to by the logs of the [L1 deposit feed contract][deposit-feed-contract]. -In the event a deposit transaction is included which is not derived by the [execution -engine][execution-engine] using the correct derivation algorithm, the resulting state transition -would be invalid. - ### Execution -In order to execute a deposit transaction: +In order to execute a deposited transaction: First, the balance of the `from` account MUST be increased by the amount of `mint`. -Then, the execution environment for a deposit transaction is initialized based on the transaction's -values, in exactly the same manner as it would be for an EIP-155 transaction. +Then, the execution environment for a deposited transaction is initialized based on the +transaction's attributes, in exactly the same manner as it would be for an EIP-155 transaction. Specifically, a new EVM call frame targeting the `to` address is created with values initialized as follows: @@ -108,7 +111,7 @@ follows: - `context.gas` set to `gasLimit` - `context.value` set to `sendValue` -#### Nonce handling +#### Nonce Handling Despite the lack of signature validation, we still increment the nonce of the `from` account when a deposit transaction is executed. In the context of a deposit-only roll up, this is not necessary @@ -118,46 +121,46 @@ tooling (such as wallets and block explorers). [create-nonce]: https://github.com/ethereum/execution-specs/blob/617903a8f8d7b50cf71bf1aa733c37897c8d75c1/src/ethereum/frontier/utils/address.py#L40 -## L1 Attributes Deposit +## L1 Attributes Deposited Transaction -[l1-attributes-deposit]: #l1-attributes-deposit +[l1-attr-deposit]: #l1-attributes-deposited-transaction -An [L1 attributes deposit] is a deposit transaction sent to the [L1 attributes predeploy][predeploy] -contract. +An [L1 attributes deposited transaction][g-l1-attr-deposit] is a deposit transaction sent to the [L1 +attributes predeployed contract][predeploy]. This transaction MUST have the following values: 1. `from` is `0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001` (the address of the [L1 Attributes depositor account][depositor-account]) -2. `to` is `0x4200000000000000000000000000000000000014` (the address of the L1 attributes predeploy - contract). +2. `to` is `0x4200000000000000000000000000000000000014` (the address of the [L1 attributes predeployed + contract][predeploy]). 3. `mint` is `0` 4. `value` is `0` 5. `gasLimit` is set to the maximum available. -6. `data` is an [ABI] encoded call to the [L1 attributes predeploy][predeploy] contract's +6. `data` is an [ABI] encoded call to the [L1 attributes predeployed contract][predeploy]'s `setL1BlockValues()` function with correct values associated with the corresponding L1 block (cf. - [reference implementation][l1-attrib-ref-implem]). + [reference implementation][l1-attr-ref-implem]). - +No gas is paid for L1 attributes deposited transactions. ## Special Accounts on L2 The L1 attributes deposit transaction involves two special purpose accounts: 1. The L1 attributes depositor account -2. The L1 attributes predeploy +2. The L1 attributes predeployed contract ### L1 Attributes Depositor Account [depositor-account]: #l1-attributes-depositor-account -The depositor account is an EOA with no known private key. It has the address +The depositor account is an [EOA][g-eoa] with no known private key. It has the address `0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001`. Its value is returned by the `CALLER` and `ORIGIN` opcodes during execution of the L1 attributes deposit transaction. -### L1 Attributes Predeploy +### L1 Attributes Predeployed Contract -[predeploy]: #l1-attributes-predeploy +[predeploy]: #l1-attributes-predeployed-contract A predeployed contract on L2 at address `0x4200000000000000000000000000000000000014`, which holds certain block variables from the corresponding L1 block in storage, so that they may be accessed @@ -171,9 +174,9 @@ The contract has the following solidity interface, and can be interacted with ac [ABI]: https://docs.soliditylang.org/en/v0.8.10/abi-spec.html -#### L1 Attributes: Reference Implementation +#### L1 Attributes Predeployed Contract: Reference Implementation -[l1-attrib-ref-implem]: #l1-attributes--reference-implementation +[l1-attr-ref-implem]: #l1-attributes-predeployed-contract--reference-implementation A reference implementation of the L1 Attributes predeploy contract can be found in [L1Block.sol]. @@ -183,14 +186,14 @@ After running `yarn build` in the `packages/contracts` directory, the bytecode t file will be located in the `deployedBytecode` field of the build artifacts file at `/packages/contracts/artifacts/contracts/L2/L1Block.sol/L1Block.json`. -## L1 Transaction Deposits +## User-Deposited Transactions -[l1-transaction-deposits]: #l1-transaction-deposits +[user-deposited]: #user-deposited-transactions -L1 [transaction deposits] are [deposit transactions][deposit-transaction-type] generated by the [L2 -Chain Derivation][derivation] process. The values of each transaction are determined by the -corresponding `TransactionDeposited` event emitted by the [deposit feed -contract][deposit-feed-contract] on L1. +[User-deposited transactions][g-user-deposited] are [deposited transactions][deposited-tx-type] +generated by the [L2 Chain Derivation][derivation] process. The content of each user-deposited +transaction are determined by the corresponding `TransactionDeposited` event emitted by the [deposit +feed contract][deposit-feed-contract] on L1. 1. `from` is unchanged from the emitted value (though it may have been transformed to an alias in the deposit feed contract). @@ -203,22 +206,20 @@ contract][deposit-feed-contract] on L1. 6. `data` is unchanged from the emitted value. Depending on the value of `to` it is handled as either calldata or initialization code depending on the value of `to`. -### Deposit Feed Contract +### Deposit Contract -[deposit-feed-contract]: #deposit-feed-contract +[deposit-contract]: #deposit-contract -The deposit feed contract is deployed to L1. Deposited transactions are derived from the values in -the `TransactionDeposited` event(s) emitted by the deposit feed contract. +The deposit contract is deployed to L1. Deposited transactions are derived from the values in +the `TransactionDeposited` event(s) emitted by the deposit contract. -The deposit feed handles two special cases: +The deposit contract handles two special cases: 1. A contract creation deposit, which is indicated by setting the `isCreation` flag to `true`. In the event that the `to` address is non-zero, the contract will revert. 2. A call from a contract account, in which case the `from` value is transformed to its L2 [alias][address-aliasing]. -> **TODO** Define if/how ETH withdrawals occur. - #### Address Aliasing [address-aliasing]: #address-aliasing @@ -229,7 +230,7 @@ has the same address as a contract on L2 but doesn't have the same code. We can for EOAs because they're guaranteed to have the same "code" (i.e. no code at all). This also makes it possible for users to interact with contracts on L2 even when the Sequencer is down. -#### Deposit Feed: Reference Implementation +#### Deposit Feed Contract: Reference Implementation A reference implementation of the Deposit Feed contract can be found in [DepositFeed.sol]. diff --git a/specs/glossary.md b/specs/glossary.md index 17bbc188..171473f6 100644 --- a/specs/glossary.md +++ b/specs/glossary.md @@ -145,8 +145,8 @@ In general, a deposit is an L2 transaction derived from an L1 block (by the [rol While transaction deposits are notably (but not only) used to "deposit" (bridge) ETH and tokens to L2, the word *deposit* should be understood as "a transaction *deposited* to L2 from L1". -This term *deposit* is somewhat ambiguous as these "transactions" exist at multiple levels. This section disambiguates all -deposit-related terms. +This term *deposit* is somewhat ambiguous as these "transactions" exist at multiple levels. This section disambiguates +all deposit-related terms. Notably, a *deposit* can refer to: @@ -331,7 +331,7 @@ this term. A [predeployed contract][predeploy] on L2 that can be used to retrieve the L1 block attributes of L1 blocks with a given block number or a given block hash. -cf. [L1 Attributes Predeployed Contract Specification](deposits.md#l1-attributes--reference-implementation) +cf. [L1 Attributes Predeployed Contract Specification](deposits.md#l1-attributes-predeployed-contract) ------------------------------------------------------------------------------------------------------------------------ From 5c2c043570427f5417d5002946825e7c9e8f6290 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Fri, 21 Jan 2022 01:57:23 +0100 Subject: [PATCH 04/12] add g-prefix to glossary links in deposits.md --- specs/deposits.md | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/specs/deposits.md b/specs/deposits.md index f675fcdc..6c375535 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -1,20 +1,19 @@ # Deposits -[transaction-type]: glossary.md#transaction-type -[derivation]: glossary.md#L2-chain-derivation -[execution-engine]: glossary.md#execution-engine -[deposited]: glossary.md#deposited -[deposits]: glossary.md#deposits +[g-transaction-type]: glossary.md#transaction-type +[g-derivation]: glossary.md#L2-chain-derivation +[g-deposited]: glossary.md#deposited +[g-deposits]: glossary.md#deposits [g-l1-attr-deposit]: glossary.md#l1-attributes-deposited-transaction [g-user-deposited]: glossary.md#user-deposited-transaction [g-deposit-block]: glossary.md#deposit-block [g-eoa]: glossary.md#eoa -[Deposited transactions], also known as [deposits] are transactions which are initiated on L1, and -executed on L2. This document outlines a new [transaction type][transaction-type] for deposits. It -also describes how deposits are initiated on L1, along with the authorization and validation -conditions on L2. +[Deposited transactions][g-deposited], also known as [deposits][g-deposits] are transactions which +are initiated on L1, and executed on L2. This document outlines a new [transaction +type][g-transaction-type] for deposits. It also describes how deposits are initiated on L1, along +with the authorization and validation conditions on L2. **Vocabulary note**: *deposited transaction* refers specifically to an L2 transaction, while *deposit* can refer to the transaction at various stages (for instance when it is deposited on L1). @@ -41,7 +40,7 @@ conditions on L2. [deposited-tx-type]: #the-deposited-transaction-type -[Deposited transactions][deposited] have the following notable distinctions from existing +[Deposited transactions][g-deposited] have the following notable distinctions from existing transaction types: 1. They are derived from Layer 1 blocks, and must be included as part of the protocol. @@ -88,7 +87,7 @@ software, and complexity in general. [authorization]: #validation-and-authorization-of-deposited-transaction As noted above, the deposited transaction type does not include a signature for validation. Rather, -authorization is handled by the [L2 chain derivation][derivation] process, which when correctly +authorization is handled by the [L2 chain derivation][g-derivation] process, which when correctly applied will only derive transactions with a `from` address attested to by the logs of the [L1 deposit feed contract][deposit-feed-contract]. @@ -191,7 +190,7 @@ file will be located in the `deployedBytecode` field of the build artifacts file [user-deposited]: #user-deposited-transactions [User-deposited transactions][g-user-deposited] are [deposited transactions][deposited-tx-type] -generated by the [L2 Chain Derivation][derivation] process. The content of each user-deposited +generated by the [L2 Chain Derivation][g-derivation] process. The content of each user-deposited transaction are determined by the corresponding `TransactionDeposited` event emitted by the [deposit feed contract][deposit-feed-contract] on L1. From 2e21031b0bdcd173f63262d8323256500aca9f9d Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Fri, 21 Jan 2022 14:39:12 +0100 Subject: [PATCH 05/12] rewrite rollup node spec to standardize terminology, add pseudocode and clarify content --- specs/exec-engine.md | 32 +++-- specs/glossary.md | 6 +- specs/rollup-node.md | 279 +++++++++++++++++++++++++++---------------- 3 files changed, 203 insertions(+), 114 deletions(-) diff --git a/specs/exec-engine.md b/specs/exec-engine.md index 23e6f48d..e3fd40f6 100644 --- a/specs/exec-engine.md +++ b/specs/exec-engine.md @@ -50,17 +50,31 @@ to [`engine_forkchoiceUpdatedV1`][engine_forkchoiceUpdatedV1]: the extended `Pay #### Extended PayloadAttributesV1 -[`PayloadAttributesV1`][PayloadAttributesV1] is extended with a `transactions` field, -equivalent to the `transactions` field in [`ExecutionPayloadV1`][ExecutionPayloadV1]: -> `Array of DATA` - Array of transaction objects, each object is a byte list ([`DATA`][exec-api-data]) representing -> `TransactionType || TransactionPayload` or `LegacyTransaction` as defined in [EIP-2718][eip-2718]. +[`PayloadAttributesV1`][PayloadAttributesV1] is extended with a `transactions` field, equivalent to +the `transactions` field in [`ExecutionPayloadV1`][ExecutionPayloadV1]: -This `transactions` field is an optional JSON field: +```js +PayloadAttributesOPV1: { + timestamp: QUANTITY + random: DATA (32 bytes) + suggestedFeeRecipient: DATA (20 bytes) + transactions: array of DATA +} +``` -- If empty or missing: no changes to engine behavior. - Utilized by sequencers (if enabled) to consume the transaction pool. +The type notation used here refers to the [HEX value encoding] used by the [Ethereum JSON-RPC API +specification][JSON-RPC-API], as this structure will need to be sent over JSON-RPC. `array` refers +to a JSON array. + +Each item of the `transactions` array is a byte list encoding a transaction: `TransactionType || +TransactionPayload` or `LegacyTransaction`, as defined in [EIP-2718][eip-2718]. + +The `transactions` field is optional: + +- If empty or missing: no changes to engine behavior. The sequencers will (if enabled) build a block + by consuming transactions from the transaction pool. - If present and non-empty: the payload MUST only be produced with this exact list of transactions. - Utilized by [rollup driver][rollup-driver] to compute full block payloads based on deterministic inputs. + The [rollup driver][rollup-driver] determines the transaction list based on deterministic L1 inputs. > **TODO**: derivation function spec in rollup node doc or separate driver doc @@ -150,3 +164,5 @@ the operation within the engine is the exact same as with L1 (although with an E [engine_forkchoiceUpdatedV1]: https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.5/src/engine/specification.md#engine_forkchoiceupdatedv1 [engine_executePayloadV1]: https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.5/src/engine/specification.md#engine_executePayloadV1 [engine_getPayloadV1]: https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.5/src/engine/specification.md#engine_getPayloadV1 +[HEX value encoding]: https://eth.wiki/json-rpc/API#hex-value-encoding +[JSON-RPC-API]: https://github.com/ethereum/execution-apis diff --git a/specs/glossary.md b/specs/glossary.md index 171473f6..d90c5a0a 100644 --- a/specs/glossary.md +++ b/specs/glossary.md @@ -24,7 +24,7 @@ - [Deposited Transaction Type](#deposited-transaction-type) - [Deposit Contract](#deposit-contract) - [Other L2 Chain Concepts](#other-l2-chain-concepts) - - [Address Aliasing](#address-aliasing) + - [Address Aliasing](#address-aliasing) - [L2 Chain Inception](#l2-chain-inception) - [Rollup Node](#rollup-node) - [Rollup Driver](#rollup-driver) @@ -195,7 +195,7 @@ That contract can then be used to read the the attributes of the L1 block corres L1 attributes deposited transactions are specified in the [L1 Attributes Deposit][l1-attributes-tx-spec] section of the deposits specification. -[l1-attributes-tx-spec]: deposits.md#l1-attributes-deposit +[l1-attributes-tx-spec]: deposits.md#l1-attributes-deposited-transaction ## User-Deposited Transaction @@ -207,7 +207,7 @@ A *user-deposited transaction* is a [deposited transaction][deposited] which is User-deposited transactions are specified in the [Transaction Deposits][tx-deposits-spec] section of the deposits specification. -[tx-deposits-spec]: deposits.md##l1-transaction-deposits +[tx-deposits-spec]: deposits.md#user-deposited-transactions ## Depositing Call diff --git a/specs/rollup-node.md b/specs/rollup-node.md index 6b00dbd0..48293ae4 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -7,21 +7,27 @@ [block]: glossary.md#block [execution engine]: glossary.md#execution-engine [reorg]: glossary.md#re-organization -[block gossip]: glossary.md#block-gossip [rollup driver]: glossary.md#rollup-driver -[deposits]: glossary.md#deposits -[deposit feed contract]: glossary.md#L2-deposit-feed-contract [L2 chain inception]: glossary.md#L2-chain-inception [receipts]: glossary.md#receipt -[L1 attributes transaction]: glossary.md#l1-attributes-transaction -[transaction deposits]: glossary.md#transaction-deposits +[L1 attributes deposit]: glossary.md#l1-attributes-deposit +[g-deposit-contract]: glossary.md#deposit-contract +[g-deposits]: glossary.md#deposits +[g-deposit-block]: glossary.md#deposit-block +[g-deposited]: glossary.md#deposited-transaction +[g-l1-attr-deposit]: glossary.md#l1-attributes-deposited-transaction +[g-user-deposited]: glossary.md#user-deposited-transaction +[g-l1-attr-predeploy]: glossary.md#l1-attributes-predeployed-contract +[g-depositing-call]: glossary.md#depositing-call +[g-depositing-transaction]: glossary.md#depositing-transaction The [rollup node] is the component responsible for [deriving the L2 chain][derivation] from L1 blocks (and their associated [receipts]). This process happens in two steps: 1. Read from L1 blocks and associated receipts, in order to generate [payload attributes] (essentially [a block without output properties][block]). -2. Pass the payload attributes to the [execution engine], so that [output block properties][block] may be computed. +2. Pass the payload attributes to the [execution engine], so that the L2 block (including [output block + properties][block]) may be computed. While this process is conceptually a pure function from the L1 chain to the L2 chain, it is in practice incremental. The L2 chain is extended whenever new L1 blocks are added to the L1 chain. Similarly, the L2 chain re-organizes whenever the @@ -33,135 +39,188 @@ concerned with the specification of the rollup driver. ## Table of Contents - [L2 Chain Derivation](#l2-chain-derivation) - - [Input derivation](#input-derivation) - - [L1 attributes transaction derivation](#l1-attributes-transaction-derivation) - - [Transaction deposits derivation](#transaction-deposits-derivation) - - [Payload attributes derivation](#payload-attributes-derivation) - - [Output derivation](#output-derivation) -- [Completing a driver step](#completing-a-driver-step) - - [Execute](#execute) - - [Forkchoice](#forkchoice) -- [API error handling](#api-error-handling) + - [From L1 Blocks to Payload Attributes](#from-l1-blocks-to-payload-attributes) + - [Reading L1 Inputs](#reading-l1-inputs) + - [Encoding the L1 Attributes Deposited Transaction](#encoding-the-l1-attributes-deposited-transaction) + - [Encoding User-Deposited Transactions](#encoding-user-deposited-transactions) + - [Building the Payload Attributes](#building-the-payload-attributes) + - [From Payload Attributes to L2 Block](#from-payload-attributes-to-L2-block) + - [Inductive Derivation Step](#inductive-derivation-step) + - [Engine API Error Handling](#engine-api-error-handling) + - [Finalization Guarantees](#finalization-guarantees) + - [Whole L2 Chain Derivation](#whole-l2-chain-derivation) - [Handling L1 Re-Orgs](#handling-l1-re-orgs) -- [Finalization Guarantees](#finalization-guarantees) -## L2 Chain Derivation +# L2 Chain Derivation -This section specifies how the [rollup driver] derives one L2 block per every L1 block. +[l2-chain-derivation]: #l2-chain-derivation -First inputs are derived from L1 source data, then outputs are derived with L2 state through the [Engine API]. +This section specifies how the [rollup driver] derives one L2 [deposit block][g-deposit-block] per every L1 block. The +L2 block carries *[deposited transactions][g-deposited]* of two kinds: -[Engine API]: exec-engine.md#engine-api +- a single *[L1 attributes deposited transaction][g-l1-attr-deposit]* (always first) +- zero or more *[user-deposited transactions][g-user-deposited]* -### Input derivation +------------------------------------------------------------------------------------------------------------------------ -The L2 block has the same format as a L1 block: a block-header and a list of transactions. +## From L1 Blocks to Payload Attributes -The list of transaction carries: +### Reading L1 inputs -- A *[L1 attributes transaction]* (always first item) -- L2 transactions deposited by users in the L1 block (*[deposits]*, if any) +The rollup reads the following data from each L1 block: -While deposits are notably (but not only) used to "deposit" (bridge) ETH and tokens to L2, -the word *deposit* should be understood as "a transaction *deposited* to L2". +- L1 block attributes + - block number + - timestamp + - basefee + - *random* (the output of the [`RANDOM` opcode][random]) +- L1 log entries emitted for [user deposits][g-deposits], augmented with + - `blockHeight`: the block-height of the L1 block + - `transactionIndex`: the transaction-index within the L2 transactions list -The L1 attributes are read from the L1 block header, while other deposits are read from the block's [receipts]. +[random]: https://eips.ethereum.org/EIPS/eip-4399 -All derived deposits each get two additional attributes during derivation, to ensure uniqueness: +> Design note: The extra log entry metadata will be used to ensure that deposited transactions will be unique. Without +> them, two different deposited transaction could have the same exact hash. +> +> We do not use the sender's nonce to ensure uniqueness because this would require an extra L2 EVM state read from the +> [execution engine]. -- `blockHeight`: the block-height of the L1 input the deposit was derived from -- `transactionIndex`: the transaction-index within the L2 transactions list +The L1 attributes are read from the L1 block header, while deposits are read from the block's [receipts]. Refer to the +[**deposit contract specification**][deposit-contract-spec] for details on how deposits are encoded as log entries. -#### L1 attributes transaction derivation +[deposit-contract-spec]: deposits.md#deposit-contract -The rollup reads the following attributes from each L1 block to derive a [L1 attributes transaction]: +### Encoding the L1 Attributes Deposited Transaction -- block number -- timestamp -- basefee -- *random* (the output of the [`RANDOM` opcode][random]) +The [L1 attributes deposited transaction][g-l1-attr-deposit] is a call that submits the L1 block attributes (listed +above) to the [L1 attributes predeployed contract][g-l1-attr-predeploy]. -These are then encoded as a [L1 attributes deposit] to update the [L1 Attributes Predeploy]. +To encode the L1 attributes deposited transaction, refer to the following sections of the deposits spec: -[random]: https://eips.ethereum.org/EIPS/eip-4399 -[L1 attributes deposit]: deposits.md#l1-attributes-deposit -[L1 Attributes Predeploy]: deposits.md#l1-attributes-predeploy +- [The Deposited Transaction Type](deposits.md#the-deposited-transaction-type) +- [L1 Attributes Deposited Transaction](deposits.md#l1-attributes-deposited-transaction) + +### Encoding User-Deposited Transactions -#### Transaction deposits derivation +A [user-deposited-transactions][g-deposited] is an L2 transaction derived from a [user deposit][g-deposits] submitted on +L1 to the [deposit contract][g-deposit-contract]. Refer to the [deposit contract specification][deposit-contract-spec] +for more details. -A [transaction deposit][transaction deposits] is an L2 transaction that has been submitted on L1, via a call to the -[deposit feed contract]. +The user-deposited transaction is derived from the log entry emitted by the [depositing call][g-depositing-call], which +is stored in the [depositing transaction][g-depositing-transaction]'s log receipt. -Refer to the [**deposit feed contract specification**][deposit-feed-spec] for details on how -deposit properties are emitted in deposit log entries. +To encode user-deposited transactions, refer to the following sections of the deposits spec: -[deposit-feed-spec]: deposits.md#deposit-feed-contract +- [The Deposited Transaction Type](deposits.md#the-deposited-transaction-type) +- [User-Deposited Transactions](deposits.md#user-deposited-transactions) -#### Payload attributes derivation +### Building the Payload Attributes -From the data read from L1, the rollup node constructs an [expanded version of PayloadAttributesV1], -which includes an additional `transactions` field. +[payload attributes]: #building-the-payload-attributes -The object properties must be set as follows: +From the data read from L1 and the encoded transactions, the rollup node constructs an [expanded version][expanded-paylod] of +[`PayloadAttributesV1`], which includes an additional `transactions` field. -- `timestamp` is set to the current [unix time], - rounded to the closest multiple of 2 seconds. No two blocks may have the same timestamp. +The object's properties must be set as follows: + +- `timestamp` is set to the timestamp of the L1 block. - `random` is set to the *random* L1 block attribute - `suggestedFeeRecipient` is set to the zero-address for deposit-blocks, since there is no sequencer. -- `transactions` is an array of the derived deposits, all encoded in the [EIP-2718] format. +- `transactions` is an array of the derived deposits, encoded as per the two preceding sections. -[expanded version of PayloadAttributesV1]: exec-engine.md#extended-payloadattributesv1 -[unix time]: https://en.wikipedia.org/wiki/Unix_time -[EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718 -[EIP-2930]: https://eips.ethereum.org/EIPS/eip-2930 +[expanded-payload]: exec-engine.md#extended-payloadattributesv1 +[`PayloadAttributesV1`]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#payloadattributesv1 -### Output derivation +------------------------------------------------------------------------------------------------------------------------ -Building a full block requires the earlier [derived payload attributes](#payload-attributes-derivation) -(`payloadAttributes` argument) as well as the previous L2 state (`forkchoiceState` argument), defined by -the [`engine_forkchoiceUpdatedV1`] method of the [Engine API]: +## From Payload Attributes to L2 Block -- `headBlockHash`: block hash of the last block of the L2 chain, according to the rollup driver. -- `safeBlockHash`: same as `headBlockHash`. -- `finalizedBlockHash`: the hash of the block whose number is `number(headBlockHash) - FINALIZATION_DELAY_BLOCKS` if - the number of that block is `>= L2_CHAIN_INCEPTION`, 0 otherwise (where `FINALIZATION_DELAY_BLOCKS == 50400` - (approximately 7 days worth of L1 blocks) and `L2_CHAIN_INCEPTION` is the [L2 chain inception] (the number of the - first L1 block for which an L2 block was produced). See the [Finalization Guarantees][finalization] section for more - details. +Once the [payload attributes] for a given L1 block `B` have been built, and if we have already derived an L2 block from +`B`'s parent block, then we can use the payload attributes to derive a new L2 block. -[`engine_forkchoiceUpdatedV1`]: exec-engine.md#engine_forkchoiceUpdatedV1 +### Inductive Derivation Step -Once this first API call completes, `engine_getPayloadV1` is used to fetch the full L2 block, -as specified in the [Engine API]. +Let -[`engine_getPayloadV1`]: exec-engine.md#engine_executepayloadv1 -[`ExecutionPayloadV1`]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#executionpayloadv1 +- `refL2` be the (hash of) the current L2 chain head +- `refL1` be the (hash of) the L1 block from which `refL2` was derived +- `payloadAttributes` be some previously derived [payload attributes] for the L1 block with number `l1Number(refL1) + 1` + +Then we can apply the following pseudocode logic to update the state of both the rollup driver and execution engine: + +``` +// request a new execution payload +forkChoiceState = { + headBlockHash: refL2, + safeBlockHash: refL2, + finalizedBlockHash: l2BlockHashAt(l2Number(refL2) - FINALIZATION_DELAY_BLOCKS) +} +(status, payloadID) = engine_forkchoiceUpdatedV1(forkChoiceState, payloadAttributes) +if (status != "SUCCESS") error() -## Completing a driver step +// retrieve and execute the execution payload +(executionPayload, error) = engine_getPayloadV1(payloadID) +if (error != null) error() +(status, latestValidHash, validationError) = engine_executePayloadV1(executionPayload) +if (status != "VALID" || validationError != null) error() -After deriving a full L2 block, two more API calls are required to persist the result: -execute the new block, and update the forkchoice to reflect the new head. +refL2 = latestValidHash +refL1 = l1HashForNumber(l1Number(refL1) + 1)) -### Execute +// update head to new refL2 +forkChoiceState = { + headBlockHash: refL2, + safeBlockHash: refL2, + finalizedBlockHash: l2BlockHashAt(l2Number(headBlockHash) - FINALIZATION_DELAY_BLOCKS) +} +(status, payloadID) = engine_forkchoiceUpdatedV1(refL2, null) +if (status != "SUCCESS") error() +``` -Execute through the [`engine_executePayloadV1`] API method with the derived payload to update the engine state. -A `"status": "VALID"` result is required to continue. +The following JSON-RPC methods are part of the [execution engine API][exec-engine]: +> **TODO** fortify the execution engine spec with more information regarding JSON-RPC, notably covering +> information found [here][json-rpc-info-1] and [here][json-rpc-info-2] + +[json-rpc-info-1]: https://github.com/ethereum-optimism/optimistic-specs/blob/a3ffa9a8c825d155a0469659b3101db5f41eecc4/specs/rollup-node.md#from-l1-blocks-to-payload-attributes +[json-rpc-info-2]: https://github.com/ethereum-optimism/optimistic-specs/blob/a3ffa9a8c825d155a0469659b3101db5f41eecc4/specs/rollup-node.md#building-the-l2-block-with-the-execution-engine + +[exec-engine]: execution-engine.md + +- [`engine_forkchoiceUpdatedV1`] — updates the forkchoice (i.e. the chain head) to `headBlockHash` if different, and + instructs the engine to start building an execution payload given payload attributes the second argument isn't `null` +- [`engine_getPayloadV1`] — retrieves a previously requested execution payload +- [`engine_executePayloadV1`] — executes an execution payload to create a block + +[`engine_forkchoiceUpdatedV1`]: exec-engine.md#engine_forkchoiceUpdatedV1 +[`engine_getPayloadV1`]: exec-engine.md#engine_executepayloadv1 [`engine_executePayloadV1`]: exec-engine.md#engine_executepayloadv1 -### Forkchoice +The execution payload is an object of type [`ExecutionPayloadV1`]. -Update the L2 head with a [`engine_forkchoiceUpdatedV1`] API call, now without `payloadAttributes` argument, -and updated `forkchoiceState` argument: +[`ExecutionPayloadV1`]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#executionpayloadv1 + +Within the `forkChoiceState` object, the properties have the following meaning: + +- `headBlockHash`: block hash of the last block of the L2 chain, according to the rollup driver. +- `safeBlockHash`: same as `headBlockHash`. +- `finalizedBlockHash`: the hash of the block whose number is `l2Number(headBlockHash) - FINALIZATION_DELAY_BLOCKS` if the + number of that block is `>= L2_CHAIN_INCEPTION`, 0 otherwise (\*) See the [Finalization Guarantees][finalization] + section for more details. -- `headBlockHash`: block hash of the derived payload -- `safeBlockHash`: same as `headBlockHash` -- `finalizedBlockHash`: finalized-block. May have changed since last call. - Not strictly required to change, this can be adjusted later. +(\*) where: -A `"status": "SUCCESS"` result then indicates if the engine successfully updated the head to the derived payload. +- `FINALIZATION_DELAY_BLOCKS == 50400` (approximately 7 days worth of L1 blocks) +- `L2_CHAIN_INCEPTION` is the [L2 chain inception] (the number of the first L1 block for which an L2 block was + produced). -## API error handling +Finally, the `error()` function signals an error that must be handled by the implementation. Refer to the next section +for more details. + +### Engine API Error Handling + +[error-handling]: #engine-api-error-handling All invocations of [`engine_forkchoiceUpdatedV1`], [`engine_getPayloadV1`] and [`engine_executePayloadV1`] by the rollup driver should not result in errors assuming conformity with the specification. Said otherwise, all errors are @@ -175,7 +234,34 @@ The following scenarios are assimilated to errors: - [`engine_executePayloadV1`] returning a `status` of `"SYNCING"` or `"INVALID"` whenever passed an execution payload that was obtained by a previous call to [`engine_getPayloadV1`]. -## Handling L1 Re-Orgs +### Finalization Guarantees + +[finalization]: #finalization-guarantees + +As stated earlier, an L2 block is considered *finalized* after a delay of `FINALIZATION_DELAY_BLOCKS == 50400` L1 blocks +after the L1 block that generated it. This is a duration of approximately 7 days worth of L1 blocks. This is also known +as the "fault proof window", as after this time the block can no longer be challenged by a fault proof. + +L1 Ethereum [reaches finality approximately every 12 minutes][l1-finality]. L2 blocks generated from finalized L1 blocks +are "safer" than most recent L2 blocks because they will never disappear from the chain's history because of a re-org. +However, they can still be challenged by a fault proof until the end of the fault proof window. + +[l1-finality]: https://www.paradigm.xyz/2021/07/ethereum-reorgs-after-the-merge/ + +> **TODO** the spec doesn't encode the notion of fault proof yet, revisit this (and include links) when it does + +## Whole L2 Chain Derivation + +The previous two sections presents an inductive process: given that we know the "current" L2 block, well as the next L1 +block, then we can derive [payload attributes] for the next L1 block, and from that the next L2 block. + +To derive the whole L2 chain from scratch, we simply start with the L2 genesis block as the current L2 block, and the +block at height `L2_CHAIN_INCEPTION + 1` as the next L1 block. Then we iteratively apply the derivation process from the +previous section to each successive L1 block until we have caught up with the L1 head. + +> **TODO** specify genesis block + +# Handling L1 Re-Orgs [l1-reorgs]: #handling-L1-re-orgs @@ -217,16 +303,3 @@ This sync starting point (L1 block to derive from, and L2 parent to build on) is Just like before, the meaning of errors returned by RPC calls is unspecified and must be handled at the implementer's discretion, while remaining compatible with the specification. - -## Finalization Guarantees - -[finalization]: #finalization-guarantees - -As already alluded to in the section on [interacting with the execution engine][calling-exec-engine], an L2 block is -considered *finalized* after a delay of `FINALIZATION_DELAY_BLOCKS == 50400` blocks after the L1 block that generated -it. This is a duration of approximately 7 days worth of L1 blocks. - -L1 Ethereum [reaches finality approximately every 12 minutes][l1-finality], so these L2 blocks can safely be considered -to be final: they will never disappear from the chain's history because of a re-org. - -[l1-finality]: https://www.paradigm.xyz/2021/07/ethereum-reorgs-after-the-merge/ From 4bf2bf1baff3bc4727e0005bc0e446a982c5e75c Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Fri, 21 Jan 2022 15:02:11 +0100 Subject: [PATCH 06/12] update execution engine specs --- specs/exec-engine.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/specs/exec-engine.md b/specs/exec-engine.md index e3fd40f6..c668c42b 100644 --- a/specs/exec-engine.md +++ b/specs/exec-engine.md @@ -2,7 +2,7 @@ This document outlines the modifications, configuration and usage of a L1 execution engine for L2. -## Deposit processing +## Depositited transaction processing The Engine interfaces abstract away transaction types with [EIP-2718][eip-2718]. @@ -14,18 +14,18 @@ and introduce L1 information to enshrined contracts in the execution state. [deposit-spec]: deposits.md -### Deposit boundaries +### Deposited transaction boundaries Transactions cannot be blindly trusted, trust is established through authentication. Unlike other transaction types deposits are not authenticated by a signature: the rollup node authenticates them, outside of the engine. -To process deposits safely, the deposits MUST be authenticated first: +To process deposited transactions safely, the deposits MUST be authenticated first: - Ingest directly through trusted Engine API - Part of sync towards a trusted block hash (trusted through previous Engine API instruction) -Deposits MUST never be consumed from the transaction pool. +Deposited transactions MUST never be consumed from the transaction pool. *The transaction pool can be disabled in a deposits-only rollup* ## Engine API From ec8aab3c422204f628babe4cbd6c469f1a587d21 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Mon, 24 Jan 2022 17:05:01 +0100 Subject: [PATCH 07/12] simplify/clarify sync start algorithm --- specs/rollup-node.md | 59 +++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/specs/rollup-node.md b/specs/rollup-node.md index 48293ae4..1cb3a8c4 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -273,33 +273,36 @@ processing the whole L1 chain since the [L2 chain inception]. > non-specificative** but shows how L1 re-orgs can be handled in practice. In practice, the L1 chain is processed incrementally. However, the L1 chain may occasionally re-organize, meaning the -head of the L1 chain changes to a block that is not the child of the previous head but rather some other descendant -of an ancestor of the previous head. In that case, the rollup driver must first search for common ancestor, and can then -continue deriving with the new canonical L1 block after the common point. - -This sync starting point (L1 block to derive from, and L2 parent to build on) is determined by: - -- Retrieve the head block of the engine (`refL2`), then determine the L1 block it was derived from (`refL1`), - and where it builds on (`parentL2`). -- Fetch the L1 block at the same height (`currentL1`): - - If not found: consider this a reorg to a shorter L1 chain, continue. -- If the L1 source considers this canonical (`currentL1 == refL1`): - - Find the next L1 block (it may not exist yet) and return that as `nextRefL1`, along with the `refL2`. - - Note: after looking up `N+1` ensure L1 has not changed during block-by-number lookups (`refL1 == nextL1_parent`). -- While have not found a block in the engine common with the canonical chain, traverse the L2 chain back until genesis: - - Each step starts by caching the previous `currentL1` as `nextRefL1`. - - Lookup the parent by hash: Each step `refL2` should equal the previous `parentL2`. - `refL1` and `parentL2` are also traversed back by parsing the `refL2` block. - - The canonical L1 block is looked up at the same height (`currentL1`). - - If not found: consider this a reorg to a shorter L1 chain, continue. - - If the engine and canonical chain match (`refL1 == currentL1`), then return that as `nextRefL1`, along with `refL2`. -- If there are no common blocks after genesis, check if `refL2` and `currentL1` match the expected genesis blocks. -- If the genesis is correct, the last cached `nextRefL1` is returned, along with the L2 genesis. - -> Note that post-[merge], the L1 chain will offer finalization guarantees meaning that it won't be able to re-org more -> than `FINALIZATION_DELAY_BLOCKS == 50400` in the past, hence preserving our finalization guarantees. +head of the L1 chain changes to a block that is not the child of the previous head but rather another descendant of an +ancestor of the previous head. In that case, the rollup driver must first search for the common L1 ancestor, and can +re-derive the L2 chain from that L1 block and onwards. + +The starting point of the re-derivation is a pair `(refL2, nextRefL1)` where `refL2` refers to the L2 block to build +upon and `nextRefL1` refers to the next L1 block to derive from (i.e. if `refL2` is derived from L1 block `refL1`, +`nextRefL1` is the canonicla L1 block at height `l1Number(refL1) + 1`). + +In practice, the happy path (no re-org) and the re-org paths are merged. The happy path is simply a special case of the +re-org path where the starting point of the re-derivation is `(currentL2Head, newL1Block)`. + +This re-derivation starting point can be found by applying the following algorithm: + +1. (Initialization) Set the initial `refL2` to the head block of the L2 execution engine. +2. Set `parentL2` to `refL2`'s parent block and `refL1` to the L1 block that `refL2` was derived from. +3. Fetch `currentL1`, the canonical L1 block at the same height as `refL1`. + - If `currentL1 == refL1`, then `refL2` was built on a canonical L1 block: + - Find the next L1 block (it may not exist yet) and return `(refL2, nextRefL1)` as the starting point of the re-derivation. + - It is necessary to ensure that no L1 re-org occured during this lookup, i.e. that `nextRefL1.parent == refL1`. + - If the next L1 block does not exist yet, there is no re-org, and nothing new to derive, and we can abort the + process. + - Otherwise, if `refL2` is the L2 genesis block, we have re-orged past the genesis block, which is an error that + requires a re-genesis of the L2 chain to fix (i.e. creating a new genesis configuration). + - Otherwise, if either `currentL1` does not exist, or `currentL1 != refL1`, set `refL2` to `parentL2` and restart this + algorithm from step 2. + - Note: if `currentL1` does not exist, it means we are in a re-org to a shorter L1 chain. + - Note: as an optimization, we can cache `currentL1` and reuse it as the next value of `nextRefL1` to avoid an + extra lookup. + +Note that post-[merge], the depth of re-orgs will be bounded by the [L1 finality delay][l1-finality] (every 2 epochs, +approximately 12 minutes). [merge]: https://ethereum.org/en/eth2/merge/ - -Just like before, the meaning of errors returned by RPC calls is unspecified and must be handled at the implementer's -discretion, while remaining compatible with the specification. From 9d544706eaa96e72afecf69ef3e1175185437369 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Mon, 24 Jan 2022 17:12:56 +0100 Subject: [PATCH 08/12] lint --- specs/rollup-node.md | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/specs/rollup-node.md b/specs/rollup-node.md index 1cb3a8c4..8fcae7b2 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -119,8 +119,8 @@ To encode user-deposited transactions, refer to the following sections of the de [payload attributes]: #building-the-payload-attributes -From the data read from L1 and the encoded transactions, the rollup node constructs an [expanded version][expanded-paylod] of -[`PayloadAttributesV1`], which includes an additional `transactions` field. +From the data read from L1 and the encoded transactions, the rollup node constructs an [expanded +version][expanded-paylod] of [`PayloadAttributesV1`], which includes an additional `transactions` field. The object's properties must be set as follows: @@ -149,7 +149,7 @@ Let Then we can apply the following pseudocode logic to update the state of both the rollup driver and execution engine: -``` +```pseudocode // request a new execution payload forkChoiceState = { headBlockHash: refL2, @@ -186,7 +186,7 @@ The following JSON-RPC methods are part of the [execution engine API][exec-engin [json-rpc-info-1]: https://github.com/ethereum-optimism/optimistic-specs/blob/a3ffa9a8c825d155a0469659b3101db5f41eecc4/specs/rollup-node.md#from-l1-blocks-to-payload-attributes [json-rpc-info-2]: https://github.com/ethereum-optimism/optimistic-specs/blob/a3ffa9a8c825d155a0469659b3101db5f41eecc4/specs/rollup-node.md#building-the-l2-block-with-the-execution-engine -[exec-engine]: execution-engine.md +[exec-engine]: exec-engine.md - [`engine_forkchoiceUpdatedV1`] — updates the forkchoice (i.e. the chain head) to `headBlockHash` if different, and instructs the engine to start building an execution payload given payload attributes the second argument isn't `null` @@ -205,8 +205,8 @@ Within the `forkChoiceState` object, the properties have the following meaning: - `headBlockHash`: block hash of the last block of the L2 chain, according to the rollup driver. - `safeBlockHash`: same as `headBlockHash`. -- `finalizedBlockHash`: the hash of the block whose number is `l2Number(headBlockHash) - FINALIZATION_DELAY_BLOCKS` if the - number of that block is `>= L2_CHAIN_INCEPTION`, 0 otherwise (\*) See the [Finalization Guarantees][finalization] +- `finalizedBlockHash`: the hash of the block whose number is `l2Number(headBlockHash) - FINALIZATION_DELAY_BLOCKS` if + the number of that block is `>= L2_CHAIN_INCEPTION`, 0 otherwise (\*) See the [Finalization Guarantees][finalization] section for more details. (\*) where: @@ -289,17 +289,19 @@ This re-derivation starting point can be found by applying the following algorit 1. (Initialization) Set the initial `refL2` to the head block of the L2 execution engine. 2. Set `parentL2` to `refL2`'s parent block and `refL1` to the L1 block that `refL2` was derived from. 3. Fetch `currentL1`, the canonical L1 block at the same height as `refL1`. - - If `currentL1 == refL1`, then `refL2` was built on a canonical L1 block: - - Find the next L1 block (it may not exist yet) and return `(refL2, nextRefL1)` as the starting point of the re-derivation. - - It is necessary to ensure that no L1 re-org occured during this lookup, i.e. that `nextRefL1.parent == refL1`. - - If the next L1 block does not exist yet, there is no re-org, and nothing new to derive, and we can abort the + +- If `currentL1 == refL1`, then `refL2` was built on a canonical L1 block: + - Find the next L1 block (it may not exist yet) and return `(refL2, nextRefL1)` as the starting point of the + re-derivation. + - It is necessary to ensure that no L1 re-org occured during this lookup, i.e. that `nextRefL1.parent == refL1`. + - If the next L1 block does not exist yet, there is no re-org, and nothing new to derive, and we can abort the process. - - Otherwise, if `refL2` is the L2 genesis block, we have re-orged past the genesis block, which is an error that +- Otherwise, if `refL2` is the L2 genesis block, we have re-orged past the genesis block, which is an error that requires a re-genesis of the L2 chain to fix (i.e. creating a new genesis configuration). - - Otherwise, if either `currentL1` does not exist, or `currentL1 != refL1`, set `refL2` to `parentL2` and restart this +- Otherwise, if either `currentL1` does not exist, or `currentL1 != refL1`, set `refL2` to `parentL2` and restart this algorithm from step 2. - - Note: if `currentL1` does not exist, it means we are in a re-org to a shorter L1 chain. - - Note: as an optimization, we can cache `currentL1` and reuse it as the next value of `nextRefL1` to avoid an + - Note: if `currentL1` does not exist, it means we are in a re-org to a shorter L1 chain. + - Note: as an optimization, we can cache `currentL1` and reuse it as the next value of `nextRefL1` to avoid an extra lookup. Note that post-[merge], the depth of re-orgs will be bounded by the [L1 finality delay][l1-finality] (every 2 epochs, From ddfe868ffc6e459132790b11fdf59e85ab5cedb8 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Mon, 24 Jan 2022 17:43:21 +0100 Subject: [PATCH 09/12] switch glossary links in rollup node spec to use g-prefix --- specs/glossary.md | 15 +++++----- specs/rollup-node.md | 67 ++++++++++++++++++++++---------------------- 2 files changed, 42 insertions(+), 40 deletions(-) diff --git a/specs/glossary.md b/specs/glossary.md index d90c5a0a..08315a2b 100644 --- a/specs/glossary.md +++ b/specs/glossary.md @@ -313,16 +313,17 @@ L2 derivation inputs include: [payload attributes]: glossary.md#payload-attributes -This term refers to data that can be derived from [L2 chain derivation inputs][deriv-inputs] found on L1, which are then -passed to the [execution engine][execution-engine] to construct L2 blocks. +This term refers to an object that can be derived from [L2 chain derivation inputs][deriv-inputs] found on L1, which are +then passed to the [execution engine][execution-engine] to construct L2 blocks. -"Payload attributes" is a term that originates and is specified in the [Ethereum Engine API specification][engine-api], -which we extend in this specification. +The payload attributes object essentially essentially encodes a [a block without output properties][block]. -cf. [Execution Engine Specification](exec-engine.md) +Payload attributes are originally specified in the [Ethereum Engine API specification][engine-api], which we expand in +the [Execution Engine Specification](exec-engine.md). -Payload attributes were historically called "L2 block inputs" in the L2 spec and you might still hear some people using -this term. +See also the [Building The Payload Attributes][building-payload-attr] section of the rollup node specification. + +[building-payload-attr]: rollup-node.md#building-the-payload-attributes ## L1 Attributes Predeployed Contract diff --git a/specs/rollup-node.md b/specs/rollup-node.md index 8fcae7b2..41a817e6 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -1,16 +1,15 @@ # Rollup Node Specification -[rollup node]: glossary.md#rollup-node -[derivation]: glossary.md#L2-chain-derivation -[payload attributes]: glossary.md#payload-attributes -[block]: glossary.md#block -[execution engine]: glossary.md#execution-engine -[reorg]: glossary.md#re-organization -[rollup driver]: glossary.md#rollup-driver -[L2 chain inception]: glossary.md#L2-chain-inception -[receipts]: glossary.md#receipt -[L1 attributes deposit]: glossary.md#l1-attributes-deposit +[g-rollup-node]: glossary.md#rollup-node +[g-derivation]: glossary.md#L2-chain-derivation +[g-payload-attr]: glossary.md#payload-attributes +[g-block]: glossary.md#block +[g-exec-engine]: glossary.md#execution-engine +[g-reorg]: glossary.md#re-organization +[g-rollup-driver]: glossary.md#rollup-driver +[g-inception]: glossary.md#L2-chain-inception +[g-receipts]: glossary.md#receipt [g-deposit-contract]: glossary.md#deposit-contract [g-deposits]: glossary.md#deposits [g-deposit-block]: glossary.md#deposit-block @@ -21,20 +20,20 @@ [g-depositing-call]: glossary.md#depositing-call [g-depositing-transaction]: glossary.md#depositing-transaction -The [rollup node] is the component responsible for [deriving the L2 chain][derivation] from L1 blocks (and their -associated [receipts]). This process happens in two steps: +The [rollup node][g-rollup-node] is the component responsible for [deriving the L2 chain][g-derivation] from L1 blocks +(and their associated [receipts][g-receipts]). This process happens in two steps: -1. Read from L1 blocks and associated receipts, in order to generate [payload attributes] (essentially [a block without - output properties][block]). -2. Pass the payload attributes to the [execution engine], so that the L2 block (including [output block - properties][block]) may be computed. +1. Read from L1 blocks and associated receipts, in order to generate [payload attributes][g-payload-attr] (essentially + [a block without output properties][g-block]). +2. Pass the payload attributes to the [execution engine][g-exec-engine], so that the L2 block (including [output block + properties][g-block]) may be computed. While this process is conceptually a pure function from the L1 chain to the L2 chain, it is in practice incremental. The L2 chain is extended whenever new L1 blocks are added to the L1 chain. Similarly, the L2 chain re-organizes whenever the -L1 chain [re-organizes][reorg]. +L1 chain [re-organizes][g-reorg]. -The part of the rollup node that derives the L2 chain is called the [rollup driver]. This document is currently only -concerned with the specification of the rollup driver. +The part of the rollup node that derives the L2 chain is called the [rollup driver][g-rollup-driver]. This document is +currently only concerned with the specification of the rollup driver. ## Table of Contents @@ -55,8 +54,8 @@ concerned with the specification of the rollup driver. [l2-chain-derivation]: #l2-chain-derivation -This section specifies how the [rollup driver] derives one L2 [deposit block][g-deposit-block] per every L1 block. The -L2 block carries *[deposited transactions][g-deposited]* of two kinds: +This section specifies how the [rollup driver][g-rollup-driver] derives one L2 [deposit block][g-deposit-block] per +every L1 block. The L2 block carries *[deposited transactions][g-deposited]* of two kinds: - a single *[L1 attributes deposited transaction][g-l1-attr-deposit]* (always first) - zero or more *[user-deposited transactions][g-user-deposited]* @@ -84,10 +83,11 @@ The rollup reads the following data from each L1 block: > them, two different deposited transaction could have the same exact hash. > > We do not use the sender's nonce to ensure uniqueness because this would require an extra L2 EVM state read from the -> [execution engine]. +> [execution engine][g-exec-engine]. -The L1 attributes are read from the L1 block header, while deposits are read from the block's [receipts]. Refer to the -[**deposit contract specification**][deposit-contract-spec] for details on how deposits are encoded as log entries. +The L1 attributes are read from the L1 block header, while deposits are read from the block's [receipts][g-receipts]. +Refer to the [**deposit contract specification**][deposit-contract-spec] for details on how deposits are encoded as log +entries. [deposit-contract-spec]: deposits.md#deposit-contract @@ -119,8 +119,9 @@ To encode user-deposited transactions, refer to the following sections of the de [payload attributes]: #building-the-payload-attributes -From the data read from L1 and the encoded transactions, the rollup node constructs an [expanded -version][expanded-paylod] of [`PayloadAttributesV1`], which includes an additional `transactions` field. +From the data read from L1 and the encoded transactions, the rollup node constructs the [payload +attributes][g-payload-attr] as an [expanded version][expanded-paylod] of the [`PayloadAttributesV1`] object, which +includes an additional `transactions` field. The object's properties must be set as follows: @@ -212,8 +213,8 @@ Within the `forkChoiceState` object, the properties have the following meaning: (\*) where: - `FINALIZATION_DELAY_BLOCKS == 50400` (approximately 7 days worth of L1 blocks) -- `L2_CHAIN_INCEPTION` is the [L2 chain inception] (the number of the first L1 block for which an L2 block was - produced). +- `L2_CHAIN_INCEPTION` is the [L2 chain inception][g-inception] (the number of the first L1 block for which an L2 block + was produced). Finally, the `error()` function signals an error that must be handled by the implementation. Refer to the next section for more details. @@ -267,15 +268,15 @@ previous section to each successive L1 block until we have caught up with the L1 The [previous section on L2 chain derivation][l2-chain-derivation] assumes linear progression of the L1 chain. It is also applicable for batch processing, meaning that any given point in time, the canonical L2 chain is given by -processing the whole L1 chain since the [L2 chain inception]. +processing the whole L1 chain since the [L2 chain inception][g-inception]. > By itself, the previous section fully specifies the behaviour of the rollup driver. **The current section is > non-specificative** but shows how L1 re-orgs can be handled in practice. -In practice, the L1 chain is processed incrementally. However, the L1 chain may occasionally re-organize, meaning the -head of the L1 chain changes to a block that is not the child of the previous head but rather another descendant of an -ancestor of the previous head. In that case, the rollup driver must first search for the common L1 ancestor, and can -re-derive the L2 chain from that L1 block and onwards. +In practice, the L1 chain is processed incrementally. However, the L1 chain may occasionally [re-organize][g-reorg], +meaning the head of the L1 chain changes to a block that is not the child of the previous head but rather another +descendant of an ancestor of the previous head. In that case, the rollup driver must first search for the common L1 +ancestor, and can re-derive the L2 chain from that L1 block and onwards. The starting point of the re-derivation is a pair `(refL2, nextRefL1)` where `refL2` refers to the L2 block to build upon and `nextRefL1` refers to the next L1 block to derive from (i.e. if `refL2` is derived from L1 block `refL1`, From a9087ce53d6953057c36d5dec741cdff603d659a Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Mon, 24 Jan 2022 17:43:38 +0100 Subject: [PATCH 10/12] add specifications for markdown style --- meta/README.md | 6 ++++++ meta/markdown-style.md | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 meta/README.md create mode 100644 meta/markdown-style.md diff --git a/meta/README.md b/meta/README.md new file mode 100644 index 00000000..5329ee3c --- /dev/null +++ b/meta/README.md @@ -0,0 +1,6 @@ +# Meta Processes + +This directory describes processes that we use to build the specification. + +- [Linting](linting.md): how to lint source files. +- [Markdown Style Guide](markdown-style.md): how to format and structure Markdown files. diff --git a/meta/markdown-style.md b/meta/markdown-style.md new file mode 100644 index 00000000..af0998f7 --- /dev/null +++ b/meta/markdown-style.md @@ -0,0 +1,42 @@ +# Markdown Style Guide + +## Linting + +Respect the [linting rules] (you can run the linter with `yarn lint`). + +Notably: + +- lines should be < 120 characters long + - in practice, some of our files are justified at 100 characters, some at 120 + +[linting rules]: linting.md#markdown + +## Links + +In general: + +- Use link references preferentially. + - e.g. `[my text][link-ref]` and then on its own line `[link-ref]: https://mylink.com` + - e.g. `[my text]` and then on its own line: `[my text]: https://mylink.com` + - exceptions: where it fits neatly on a single line, in particular in lists of links +- Excepted for internal and glossary links (see below), add the link reference definition directly + after the paragraph where the link first appears. + +### Glossary + +- Use links to the [glossary] liberally. +- Include the references to all the glossary links at the top of the file, under the top-level + title. +- A glossary link reference should start with the `g-` prefix. This enables to see what links to the + glossary at a glance when editing the specification. + - e.g. `[g-block]: glossary.md#block` +- Example: [Rollup Node Specification source][rollup-node] + +[glossary]: ../specs/glossary.md +[rollup-node]: https://raw.githubusercontent.com/ethereum-optimism/optimistic-specs/main/specs/rollup-node.md + +## Internal (In-File) Links + +If linking to another heading to the same file, add the link reference directly under that heading. +This makes it easier to keep the heading and the link in-sync, and signals that the heading is being +linked to from elsewhere. From 310ff922df375c8006b3c571df4d7a4c7ce82be4 Mon Sep 17 00:00:00 2001 From: Nicolas Laurent Date: Fri, 28 Jan 2022 01:11:38 +0100 Subject: [PATCH 11/12] terminology quickfix Co-authored-by: Maurelian --- specs/deposits.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/deposits.md b/specs/deposits.md index 6c375535..e57c4894 100644 --- a/specs/deposits.md +++ b/specs/deposits.md @@ -155,7 +155,7 @@ The L1 attributes deposit transaction involves two special purpose accounts: The depositor account is an [EOA][g-eoa] with no known private key. It has the address `0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001`. Its value is returned by the `CALLER` and `ORIGIN` -opcodes during execution of the L1 attributes deposit transaction. +opcodes during execution of the L1 attributes deposited transaction. ### L1 Attributes Predeployed Contract From 04309c99d6514c96a4380717cca43f2364f2d2af Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Fri, 28 Jan 2022 01:16:50 +0100 Subject: [PATCH 12/12] add precisions regarding the re-org past genesis scenario --- specs/rollup-node.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/specs/rollup-node.md b/specs/rollup-node.md index 41a817e6..b9f8ad29 100644 --- a/specs/rollup-node.md +++ b/specs/rollup-node.md @@ -298,7 +298,8 @@ This re-derivation starting point can be found by applying the following algorit - If the next L1 block does not exist yet, there is no re-org, and nothing new to derive, and we can abort the process. - Otherwise, if `refL2` is the L2 genesis block, we have re-orged past the genesis block, which is an error that - requires a re-genesis of the L2 chain to fix (i.e. creating a new genesis configuration). + requires a re-genesis of the L2 chain to fix (i.e. creating a new genesis + configuration) (\*) - Otherwise, if either `currentL1` does not exist, or `currentL1 != refL1`, set `refL2` to `parentL2` and restart this algorithm from step 2. - Note: if `currentL1` does not exist, it means we are in a re-org to a shorter L1 chain. @@ -308,4 +309,8 @@ This re-derivation starting point can be found by applying the following algorit Note that post-[merge], the depth of re-orgs will be bounded by the [L1 finality delay][l1-finality] (every 2 epochs, approximately 12 minutes). +(\*) Post-merge, this is only possible for 12 minutes. In practice, we'll pick an already-finalized L1 block as L2 +inception point to preclude the possibility of a re-org past genesis, at the cost of a few empty blocks at the start of +the L2 chain. + [merge]: https://ethereum.org/en/eth2/merge/