diff --git a/specs/SUMMARY.md b/specs/SUMMARY.md index 2e8f898..f85444d 100644 --- a/specs/SUMMARY.md +++ b/specs/SUMMARY.md @@ -16,7 +16,6 @@ - [Rollup Node](./protocol/rollup-node.md) - [Rollup Node P2P](./protocol/rollup-node-p2p.md) - [Derivation](./protocol/derivation.md) - - [Span Batches](./protocol/span-batches.md) - [Batch Submitter](./protocol/batcher.md) - [Validator](./protocol/validation.md) - [KRO-based Validator System](protocol/validator-v2/overview.md) @@ -24,6 +23,16 @@ - [Asset Manager](protocol/validator-v2/asset-manager.md) - [Predeploys](./protocol/predeploys.md) - [System Config](./protocol/system-config.md) + - [Protocol Upgrades]() + - [Regolith](./protocol/regolith/overview.md) + - [Canyon](./protocol/canyon/overview.md) + - [Delta](./protocol/delta/overview.md) + - [Span Batches](./protocol/delta/span-batches.md) + - [Ecotone](./protocol/ecotone/overview.md) + - [Derivation](./protocol/ecotone/derivation.md) + - [L1 attributes](./protocol/ecotone/l1-attributes.md) + - [Kroma MPT Migration](./protocol/mpt-migration/overview.md) + - [Execution Engine](./protocol/mpt-migration/exec-engine.md) - [ZK Fault Proof]() - [Challenge](zk-fault-proof/challenge.md) - [zkVM Prover](zk-fault-proof/zkvm-prover.md) diff --git a/specs/protocol/canyon/overview.md b/specs/protocol/canyon/overview.md new file mode 100644 index 0000000..fef176b --- /dev/null +++ b/specs/protocol/canyon/overview.md @@ -0,0 +1,46 @@ +# Canyon + + + +**Table of Contents** + +- [Execution Layer](#execution-layer) +- [Consensus Layer](#consensus-layer) + + + +[eip3651]: https://eips.ethereum.org/EIPS/eip-3651 +[eip3855]: https://eips.ethereum.org/EIPS/eip-3855 +[eip3860]: https://eips.ethereum.org/EIPS/eip-3860 +[eip4895]: https://eips.ethereum.org/EIPS/eip-4895 +[eip6049]: https://eips.ethereum.org/EIPS/eip-6049 + +[block-validation]: ../rollup-node-p2p.md#block-validation +[payload-attributes]: ../derivation.md#building-individual-payload-attributes +[1559-params]: ../exec-engine.md#1559-parameters +[channel-reading]: ../derivation.md#reading +[deposit-reading]: ../deposits.md#deposit-receipt +[create2deployer]: ../predeploys.md#create2deployer + +The Canyon upgrade contains the Shapella upgrade from L1 and some minor protocol fixes. +The Canyon upgrade uses a _L2 block-timestamp_ activation-rule, and is specified in both the +rollup-node (`canyon_time`) and execution engine (`config.canyonTime`). Shanghai time in the +execution engine should be set to the same time as the Canyon time. + +## Execution Layer + +- Shapella Upgrade + - [EIP-3651: Warm COINBASE][eip3651] + - [EIP-3855: PUSH0 instruction][eip3855] + - [EIP-3860: Limit and meter initcode][eip3860] + - [EIP-4895: Beacon chain push withdrawals as operations][eip4895] + - [Withdrawals are prohibited in P2P Blocks][block-validation] + - [Withdrawals should be set to the empty array with Canyon][payload-attributes] + - [EIP-6049: Deprecate SELFDESTRUCT][eip6049] +- [Modifies the EIP-1559 Denominator][1559-params] +- [Adds the deposit nonce & deposit nonce version to the deposit receipt hash][deposit-reading] +- [Deploys the create2Deployer to `0x13b0D85CcB8bf860b6b79AF3029fCA081AE9beF2`][create2deployer] + +## Consensus Layer + +- [Channel Ordering Fix][channel-reading] diff --git a/specs/protocol/delta/overview.md b/specs/protocol/delta/overview.md new file mode 100644 index 0000000..8ea1371 --- /dev/null +++ b/specs/protocol/delta/overview.md @@ -0,0 +1,17 @@ +# Delta + + + +**Table of Contents** + +- [Consensus Layer](#consensus-layer) + + + +The Delta upgrade uses a _L2 block-timestamp_ activation-rule, and is specified only in the rollup-node (`delta_time`). + +## Consensus Layer + +[span-batches]: ./span-batches.md + +The Delta upgrade consists of a single consensus-layer feature: [Span Batches][span-batches]. diff --git a/specs/protocol/span-batches.md b/specs/protocol/delta/span-batches.md similarity index 89% rename from specs/protocol/span-batches.md rename to specs/protocol/delta/span-batches.md index bf5d82b..4b05242 100644 --- a/specs/protocol/span-batches.md +++ b/specs/protocol/delta/span-batches.md @@ -6,9 +6,9 @@ - [Introduction](#introduction) - [Span batch format](#span-batch-format) - - [Max span-batch size](#max-span-batch-size) + - [Span Batch Size Limits](#span-batch-size-limits) - [Future batch-format extension](#future-batch-format-extension) -- [Span batch Activation Rule](#span-batch-activation-rule) +- [Span Batch Activation Rule](#span-batch-activation-rule) - [Optimization Strategies](#optimization-strategies) - [Truncating information and storing only necessary data](#truncating-information-and-storing-only-necessary-data) - [`tx_data_headers` removal from initial specs](#tx_data_headers-removal-from-initial-specs) @@ -18,7 +18,7 @@ - [Store `y_parity` and `protected_bit` instead of `v`](#store-y_parity-and-protected_bit-instead-of-v) - [Adjust `txs` Data Layout for Better Compression](#adjust-txs-data-layout-for-better-compression) - [`fee_recipients` Encoding Scheme](#fee_recipients-encoding-scheme) -- [How derivation works with Span Batch?](#how-derivation-works-with-span-batch) +- [How Derivation works with Span Batches](#how-derivation-works-with-span-batches) - [Integration](#integration) - [Channel Reader (Batch Decoding)](#channel-reader-batch-decoding) - [Batch Queue](#batch-queue) @@ -28,7 +28,13 @@ -[g-deposit-tx-type]: ../glossary.md#deposited-transaction-type +[g-deposit-tx-type]: ../../glossary.md#deposited-transaction-type +[derivation]: ../derivation.md +[channel-format]: ../derivation.md#channel-format +[batch-format]: ../derivation.md#batch-format +[frame-format]: ../derivation.md#frame-format +[batch-queue]: ../derivation.md#batch-queue +[batcher]: ../batcher.md ## Introduction @@ -40,11 +46,11 @@ The overhead is reduced by representing a span of consecutive L2 blocks in a more efficient manner, while preserving the same consistency checks as regular batch data. -Note that the [channel](./derivation.md#channel-format) and -[frame](./derivation.md#frame-format) formats stay the same: +Note that the [channel][channel-format] and +[frame][frame-format] formats stay the same: data slicing, packing and multi-transaction transport is already optimized. -The overhead in the [V0 batch format](./derivation.md) comes from: +The overhead in the [V0 batch format][derivation] comes from: - The meta-data attributes are repeated for every L2 block, while these are mostly implied already: - parent hash (32 bytes) @@ -67,9 +73,9 @@ Span-batches address these inefficiencies, with a new batch format version. [span-batch-format]: #span-batch-format Note that span-batches, unlike previous singular batches, -encode *a range of consecutive* L2 blocks at the same time. +encode _a range of consecutive_ L2 blocks at the same time. -Introduce version `1` to the [batch-format](./derivation.md#batch-format) table: +Introduce version `1` to the [batch-format][batch-format] table: | `batch_version` | `content` | | --------------- | ------------------- | @@ -133,22 +139,21 @@ tx_sigs ++ tx_tos ++ tx_datas ++ tx_nonces ++ tx_gases ++ protected_bits` [EIP-1559]: https://eips.ethereum.org/EIPS/eip-1559 [EIP-155]: https://eips.ethereum.org/EIPS/eip-155 -### Max span-batch size +### Span Batch Size Limits -Total size of encoded span batch is limited to `MAX_SPAN_BATCH_SIZE` (currently 10,000,000 bytes, -equal to `MAX_RLP_BYTES_PER_CHANNEL`). Therefore every field size of span batch will be implicitly limited to -`MAX_SPAN_BATCH_SIZE` . There can be at least single span batch per channel, and channel size is limited -to `MAX_RLP_BYTES_PER_CHANNEL` and you may think that there is already an implicit limit. However, having an explicit -limit for span batch is helpful for several reasons. We may save computation costs by avoiding malicious input while -decoding. For example, let's say bad batcher wrote span batch which `block_count = max.Uint64`. We may early return -using the explicit limit, not trying to consume data until EOF is reached. We can also safely preallocate memory for -decoding because we know the upper limit of memory usage. +The total size of an encoded span batch is limited to `MAX_RLP_BYTES_PER_CHANNEL`, which is defined in the +[Protocol Parameters table](../derivation.md#protocol-parameters). +This is done at the channel level rather than at the span batch level. + +In addition to the byte limit, the number of blocks, and total transactions is limited to `MAX_SPAN_BATCH_ELEMENT_COUNT` +. This does imply that the max number of transactions per block is also `MAX_SPAN_BATCH_ELEMENT_COUNT`. +`MAX_SPAN_BATCH_ELEMENT_COUNT` is defined in [Protocol Parameters table](../derivation.md#protocol-parameters). ### Future batch-format extension This is an experimental extension of the span-batch format, and not activated with the Delta upgrade yet. -Introduce version `2` to the [batch-format](derivation.md#batch-format) table: +Introduce version `2` to the [batch-format][batch-format] table: | `batch_version` | `content` | | --------------- | ------------------- | @@ -167,7 +172,7 @@ Where: - `fee_recipients_idxs`: for each block, `uvarint` number of index to decode fee recipients from `fee_recipients_set`. -## Span batch Activation Rule +## Span Batch Activation Rule The span batch upgrade is activated based on timestamp. @@ -225,11 +230,10 @@ Deposit transactions are excluded in batches and are never written at L1 so excl ### Adjust `txs` Data Layout for Better Compression -There are (7 choose 2) * 5! = 2520 permutations of ordering fields of `txs`. -It is not 7! because `contract_creation_bits` must be first decoded in order to decode `tx_tos`. -We experimented to find out the best layout for compression. -It turned out placing random data together(`TxSigs`, `TxTos`, `TxDatas`), -then placing leftovers helped gzip to gain more size reduction. +There are (8 choose 2) \* 6! = 20160 permutations of ordering fields of `txs`. It is not 8! +because `contract_creation_bits` must be first decoded in order to decode `tx_tos`. We +experimented with different data layouts and found that segregating random data (`tx_sigs`, +`tx_tos`, `tx_datas`) from the rest most improved the zlib compression ratio. ### `fee_recipients` Encoding Scheme @@ -242,7 +246,7 @@ we thought sequencer rotation happens not much often, so assumed that `K` will b The assumption makes upper inequality to hold. Therefore, we decided to manage `fee_recipients_idxs` and `fee_recipients_set` separately. This adds complexity but reduces data. -## How derivation works with Span Batch? +## How Derivation works with Span Batches - Block Timestamp - The first L2 block's block timestamp is `rel_timestamp + L2Genesis.Timestamp`. @@ -282,7 +286,7 @@ Span-batches share the same queue with v0 batches: batches are processed in L1 i A set of modified validation rules apply to the span-batches. -Rules are enforced with the [contextual definitions](./derivation.md#batch-queue) as v0-batch validation: +Rules are enforced with the [contextual definitions][batch-queue] as v0-batch validation: `epoch`, `inclusion_block_number`, `next_timestamp` Definitions: @@ -307,7 +311,7 @@ Span-batch rules, in validation order: - `batch.parent_check != prev_l2_block.hash[:20]` -> `drop`: i.e. the checked part of the parent hash must be equal to the same part of the corresponding L2 block hash. - Sequencing-window checks: - - Note: The sequencing window is enforced for the *batch as a whole*: + - Note: The sequencing window is enforced for the _batch as a whole_: if the batch was partially invalid instead, it would drop the oldest L2 blocks, which makes the later L2 blocks invalid. - Variables: @@ -328,7 +332,7 @@ Span-batch rules, in validation order: - `start_epoch_num < prev_l2_block.l1_origin.number` -> `drop`: epoch number cannot be older than the origin of parent block - Max Sequencer time-drift checks: - - Note: The max time-drift is enforced for the *batch as a whole*, to keep the possible output variants small. + - Note: The max time-drift is enforced for the _batch as a whole_, to keep the possible output variants small. - Variables: - `block_input`: an L2 block from the span-batch, with L1 origin as derived from the `origin_bits` and now established canonical L1 chain. @@ -383,6 +387,6 @@ not directly call `(co *ChannelOut) AddBatch` but defer that until a minimum num Output-size estimation of the queued up blocks is not possible until the span-batch is written to the channel. Past a given number of blocks, the channel may be written for estimation, and then re-written if more blocks arrive. -The [batcher functionality](./batcher.md) stays the same otherwise: unsafe blocks are transformed into batches, +The [batcher functionality][batcher] stays the same otherwise: unsafe blocks are transformed into batches, encoded in compressed channels, and then split into frames for submission to L1. Batcher implementations can implement different heuristics and re-attempts to build the most gas-efficient data-txs. diff --git a/specs/protocol/deposits.md b/specs/protocol/deposits.md index 0e6f739..18ed0d8 100644 --- a/specs/protocol/deposits.md +++ b/specs/protocol/deposits.md @@ -16,6 +16,7 @@ - [L1 Attributes Deposited Transaction Calldata](#l1-attributes-deposited-transaction-calldata) - [L1 Attributes - Genesis, Canyon, Delta](#l1-attributes---genesis-canyon-delta) - [L1 Attributes - Ecotone](#l1-attributes---ecotone) + - [L1 Attributes - Kroma MPT](#l1-attributes---kroma-mpt) - [Special Accounts on L2](#special-accounts-on-l2) - [L1 Attributes Depositor Account](#l1-attributes-depositor-account) - [L1 Attributes Predeployed Contract](#l1-attributes-predeployed-contract) @@ -299,6 +300,24 @@ and also set the following new attributes: Or `1` if the L1 block does not support blobs. The `1` value is derived from the EIP-4844 `MIN_BLOB_GASPRICE`. +#### L1 Attributes - Kroma MPT + +After Kroma MPT activation, the calldata of the L1 attributes deposited transaction excludes the deprecated +`validatorRewardScalar` argument. The overall calldata layout is as follows: + +| Input arg | Type | Calldata bytes | Segment | +|-----------------------| ------- |----------------|---------| +| {0x440a5e20} | | 0-3 | n/a | +| baseFeeScalar | uint32 | 4-7 | 1 | +| blobBaseFeeScalar | uint32 | 8-11 | | +| sequenceNumber | uint64 | 12-19 | | +| l1BlockTimestamp | uint64 | 20-27 | | +| l1BlockNumber | uint64 | 28-35 | | +| basefee | uint256 | 36-67 | 2 | +| blobBaseFee | uint256 | 68-99 | 3 | +| l1BlockHash | bytes32 | 100-131 | 4 | +| batcherHash | bytes32 | 132-163 | 5 | + ## Special Accounts on L2 The L1 attributes deposit transaction involves two special purpose accounts: diff --git a/specs/protocol/derivation.md b/specs/protocol/derivation.md index b8f118e..e05e8f3 100644 --- a/specs/protocol/derivation.md +++ b/specs/protocol/derivation.md @@ -17,8 +17,6 @@ - [L2 Chain Derivation Pipeline](#l2-chain-derivation-pipeline) - [L1 Traversal](#l1-traversal) - [L1 Retrieval](#l1-retrieval) - - [Ecotone: Blob Retrieval](#ecotone-blob-retrieval) - - [Blob Encoding](#blob-encoding) - [Frame Queue](#frame-queue) - [Channel Bank](#channel-bank) - [Pruning](#pruning) @@ -489,98 +487,6 @@ on to the next phase. [`to`]: https://github.com/ethereum/execution-specs/blob/3fe6514f2d9d234e760d11af883a47c1263eff51/src/ethereum/frontier/fork_types.py#L52C31-L52C31 -#### Ecotone: Blob Retrieval - -With the Ecotone upgrade the retrieval stage is extended to support an additional DA source: -[EIP-4844] blobs. After the Ecotone upgrade we modify the iteration over batcher transactions to -treat transactions of transaction-type == `0x03` (`BLOB_TX_TYPE`) differently. If the batcher -transaction is a blob transaction, then its calldata MUST be ignored should it be present. Instead: - -- For each blob hash in `blob_versioned_hashes`, retrieve the blob that matches it. A blob may be - retrieved from any of a number different sources. Retrieval from a local beacon-node, through - the `/eth/v1/beacon/blob_sidecars/` endpoint, with `indices` filter to skip unrelated blobs, is - recommended. For each retrieved blob: - - The blob SHOULD (MUST, if the source is untrusted) be cryptographically verified against its - versioned hash. - - If the blob has a [valid encoding](#blob-encoding), decode it into its continuous byte-string - and pass that on to the next phase. Otherwise the blob is ignored. - -Note that batcher transactions of type blob must be processed in the same loop as other batcher -transactions to preserve the invariant that batches are always processed in the order they appear -in the block. We ignore calldata in blob transactions so that it may be used in the future for -batch metadata or other purposes. - -##### Blob Encoding - -Each blob in a [EIP-4844] transaction really consists of `FIELD_ELEMENTS_PER_BLOB = 4096` field elements. - -Each field element is a number in a prime field of -`BLS_MODULUS = 52435875175126190479447740508185965837690552500527637822603658699938581184513`. -This number does not represent a full `uint256`: `math.log2(BLS_MODULUS) = 254.8570894...` - -The [L1 consensus-specs](https://github.com/ethereum/consensus-specs/blob/dev/specs/deneb/polynomial-commitments.md) -describe the encoding of this polynomial. -The field elements are encoded as big-endian integers (`KZG_ENDIANNESS = big`). - -To save computational overhead, only `254` bits per field element are used for rollup data. - -`127` bytes of application-layer rollup data is encoded at a time, into 4 adjacent field elements of the blob: - -```python -# read(N): read the next N bytes from the application-layer rollup-data. The next read starts where the last stopped. -# write(V): append V (one or more bytes) to the raw blob. -bytes tailA = read(31) -byte x = read(1) -byte A = x & 0b0011_1111 -write(A) -write(tailA) - -bytes tailB = read(31) -byte y = read(1) -byte B = (y & 0b0000_1111) | (x & 0b1100_0000) >> 2) -write(B) -write(tailB) - -bytes tailC = read(31) -byte z = read(1) -byte C = z & 0b0011_1111 -write(C) -write(tailC) - -bytes tailD = read(31) -byte D = ((z & 0b1100_0000) >> 2) | ((y & 0b1111_0000) >> 4) -write(D) -write(tailD) -``` - -Each written field element looks like this: - -- Starts with one of the prepared 6-bit left-padded byte values, to keep the field element within valid range. -- Followed by 31 bytes of application-layer data, to fill the low 31 bytes of the field element. - -The written output should look like this: - -```text -<----- element 0 -----><----- element 1 -----><----- element 2 -----><----- element 3 -----> -| byte A | tailA... || byte B | tailB... || byte C | tailC... || byte D | tailD... | -``` - -The above is repeated 1024 times, to fill all `4096` elements, -with a total of `(4 * 31 + 3) * 1024 = 130048` bytes of data. - -When decoding a blob, the top-most two bits of each field-element must be 0, -to make the encoding/decoding bijective. - -The first byte of rollup-data (second byte in first field element) is used as a version-byte. - -In version `0`, the next 3 bytes of data are used to encode the length of the rollup-data, as big-endian `uint24`. -Any trailing data, past the length delimiter, must be 0, to keep the encoding/decoding bijective. -If the length is larger than `130048 - 4`, the blob is invalid. - -If any of the encoding is invalid, the blob as whole must be ignored. - -[EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 - ### Frame Queue The Frame Queue buffers one data-transaction at a time, diff --git a/specs/protocol/ecotone/derivation.md b/specs/protocol/ecotone/derivation.md new file mode 100644 index 0000000..eefd171 --- /dev/null +++ b/specs/protocol/ecotone/derivation.md @@ -0,0 +1,105 @@ +# Derivation + + + +**Table of Contents** + +- [Ecotone: Blob Retrieval](#ecotone-blob-retrieval) +- [Blob Encoding](#blob-encoding) + + + +## Ecotone: Blob Retrieval + +With the Ecotone upgrade the retrieval stage is extended to support an additional DA source: +[EIP-4844] blobs. After the Ecotone upgrade we modify the iteration over batcher transactions to +treat transactions of transaction-type == `0x03` (`BLOB_TX_TYPE`) differently. If the batcher +transaction is a blob transaction, then its calldata MUST be ignored should it be present. Instead: + +- For each blob hash in `blob_versioned_hashes`, retrieve the blob that matches it. A blob may be + retrieved from any of a number different sources. Retrieval from a local beacon-node, through + the `/eth/v1/beacon/blob_sidecars/` endpoint, with `indices` filter to skip unrelated blobs, is + recommended. For each retrieved blob: + - The blob SHOULD (MUST, if the source is untrusted) be cryptographically verified against its + versioned hash. + - If the blob has a [valid encoding](#blob-encoding), decode it into its continuous byte-string + and pass that on to the next phase. Otherwise the blob is ignored. + +Note that batcher transactions of type blob must be processed in the same loop as other batcher +transactions to preserve the invariant that batches are always processed in the order they appear +in the block. We ignore calldata in blob transactions so that it may be used in the future for +batch metadata or other purposes. + +## Blob Encoding + +Each blob in a [EIP-4844] transaction really consists of `FIELD_ELEMENTS_PER_BLOB = 4096` field elements. + +Each field element is a number in a prime field of +`BLS_MODULUS = 52435875175126190479447740508185965837690552500527637822603658699938581184513`. +This number does not represent a full `uint256`: `math.log2(BLS_MODULUS) = 254.8570894...` + +The [L1 consensus-specs](https://github.com/ethereum/consensus-specs/blob/dev/specs/deneb/polynomial-commitments.md) +describe the encoding of this polynomial. +The field elements are encoded as big-endian integers (`KZG_ENDIANNESS = big`). + +To save computational overhead, only `254` bits per field element are used for rollup data. + +For efficient data encoding, `254` bits (equivalent to `31.75` bytes) are utilized. +`4` elements combine to effectively use `127` bytes. + +`127` bytes of application-layer rollup data is encoded at a time, into 4 adjacent field elements of the blob: + +```python +# read(N): read the next N bytes from the application-layer rollup-data. The next read starts where the last stopped. +# write(V): append V (one or more bytes) to the raw blob. +bytes tailA = read(31) +byte x = read(1) +byte A = x & 0b0011_1111 +write(A) +write(tailA) + +bytes tailB = read(31) +byte y = read(1) +byte B = (y & 0b0000_1111) | (x & 0b1100_0000) >> 2) +write(B) +write(tailB) + +bytes tailC = read(31) +byte z = read(1) +byte C = z & 0b0011_1111 +write(C) +write(tailC) + +bytes tailD = read(31) +byte D = ((z & 0b1100_0000) >> 2) | ((y & 0b1111_0000) >> 4) +write(D) +write(tailD) +``` + +Each written field element looks like this: + +- Starts with one of the prepared 6-bit left-padded byte values, to keep the field element within valid range. +- Followed by 31 bytes of application-layer data, to fill the low 31 bytes of the field element. + +The written output should look like this: + +```text +<----- element 0 -----><----- element 1 -----><----- element 2 -----><----- element 3 -----> +| byte A | tailA... || byte B | tailB... || byte C | tailC... || byte D | tailD... | +``` + +The above is repeated 1024 times, to fill all `4096` elements, +with a total of `(4 * 31 + 3) * 1024 = 130048` bytes of data. + +When decoding a blob, the top-most two bits of each field-element must be 0, +to make the encoding/decoding bijective. + +The first byte of rollup-data (second byte in first field element) is used as a version-byte. + +In version `0`, the next 3 bytes of data are used to encode the length of the rollup-data, as big-endian `uint24`. +Any trailing data, past the length delimiter, must be 0, to keep the encoding/decoding bijective. +If the length is larger than `130048 - 4`, the blob is invalid. + +If any of the encoding is invalid, the blob as a whole must be ignored. + +[EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 diff --git a/specs/protocol/ecotone/l1-attributes.md b/specs/protocol/ecotone/l1-attributes.md new file mode 100644 index 0000000..1bd4ed3 --- /dev/null +++ b/specs/protocol/ecotone/l1-attributes.md @@ -0,0 +1,108 @@ +# Ecotone L1 Attributes + + + +**Table of Contents** + +- [Overview](#overview) +- [L1 Attributes Predeployed Contract](#l1-attributes-predeployed-contract) + - [Ecotone L1Block upgrade](#ecotone-l1block-upgrade) + + + +## Overview + +On the Ecotone activation block, and if Ecotone is not activated at Genesis, +the L1 Attributes Transaction includes a call to `setL1BlockValues()` +because the L1 Attributes transaction precedes the [Ecotone Upgrade Transactions][ecotone-upgrade-txs], +meaning that `setL1BlockValuesEcotone` is not guaranteed to exist yet. + +Every subsequent L1 Attributes transaction should include a call to the `setL1BlockValuesEcotone()` function. +The input args are no longer ABI encoded function parameters, +but are instead packed into 5 32-byte aligned segments (starting after the function selector). +Each unsigned integer argument is encoded as big-endian using a number of bytes corresponding to the underlying type. +The overall calldata layout is as follows: + +[ecotone-upgrade-txs]: derivation.md#network-upgrade-automation-transactions + +| Input arg | Type | Calldata bytes | Segment | +| ----------------- | ------- | -------------- | ------- | +| {0x440a5e20} | | 0-3 | n/a | +| baseFeeScalar | uint32 | 4-7 | 1 | +| blobBaseFeeScalar | uint32 | 8-11 | | +| sequenceNumber | uint64 | 12-19 | | +| l1BlockTimestamp | uint64 | 20-27 | | +| l1BlockNumber | uint64 | 28-35 | | +| basefee | uint256 | 36-67 | 2 | +| blobBaseFee | uint256 | 68-99 | 3 | +| l1BlockHash | bytes32 | 100-131 | 4 | +| batcherHash | bytes32 | 132-163 | 5 | + +Total calldata length MUST be exactly 164 bytes, implying the sixth and final segment is only +partially filled. This helps to slow database growth as every L2 block includes a L1 Attributes +deposit transaction. + +In the first L2 block after the Ecotone activation block, the Ecotone L1 attributes are first used. + +The pre-Ecotone values are migrated over 1:1. +Blocks after the Ecotone activation block contain all pre-Ecotone values 1:1, +and also set the following new attributes: + +- The `baseFeeScalar` is set to the pre-Ecotone `scalar` value. +- The `blobBaseFeeScalar` is set to `0`. +- The pre-Ecotone `overhead` attribute is dropped. +- The `blobBaseFee` is set to the L1 blob base fee of the L1 origin block. + Or `1` if the L1 block does not support blobs. + The `1` value is derived from the EIP-4844 `MIN_BLOB_GASPRICE`. + +## L1 Attributes Predeployed Contract + +[sys-config]: ../system-config.md + +The L1 Attributes predeploy stores the following values: + +- L1 block attributes: + - `number` (`uint64`) + - `timestamp` (`uint64`) + - `basefee` (`uint256`) + - `hash` (`bytes32`) + - `blobBaseFee` (`uint256`) +- `sequenceNumber` (`uint64`): This equals the L2 block number relative to the start of the epoch, + i.e. the L2 block distance to the L2 block height that the L1 attributes last changed, + and reset to 0 at the start of a new epoch. +- System configurables tied to the L1 block, see [System configuration specification][sys-config]: + - `batcherHash` (`bytes32`): A versioned commitment to the batch-submitter(s) currently operating. + - `baseFeeScalar` (`uint32`): system configurable to scale the `basefee` in the Ecotone l1 cost computation + - `blobBasefeeScalar` (`uint32`): system configurable to scale the `blobBaseFee` in the Ecotone l1 cost computation + +The `overhead` and `scalar` values can continue to be accessed after the Ecotone activation block, +but no longer have any effect on system operation. These fields were also known as the `l1FeeOverhead` +and the `l1FeeScalar`. + +After running `pnpm build` in the `packages/contracts` directory, the bytecode to add to +the genesis file will be located in the `deployedBytecode` field of the build artifacts file at +`/packages/contracts/forge-artifacts/L1Block.sol/L1Block.json`. + +### Ecotone L1Block upgrade + +The L1 Attributes Predeployed contract, `L1Block.sol`, is upgraded as part of the Ecotone upgrade. +The version is incremented to `1.1.0`, one new storage slot is introduced, and one existing slot +begins to store additional data: + +- `blobBaseFee` (`uint256`): The L1 blob base fee. +- `blobBaseFeeScalar` (`uint32`): The scalar value applied to the L1 blob base fee portion of the L1 cost. +- `baseFeeScalar` (`uint32`): The scalar value applied to the L1 base fee portion of the L1 cost. + +The function called by the L1 attributes transaction depends on the network upgrade: + +- Before the Ecotone activation: + - `setL1BlockValues` is called, following the pre-Ecotone L1 attributes rules. +- At the Ecotone activation block: + - `setL1BlockValues` function MUST be called, except if activated at genesis. + The contract is upgraded later in this block, to support `setL1BlockValuesEcotone`. +- After the Ecotone activation: + - `setL1BlockValues` function is deprecated and MUST never be called. + - `setL1BlockValuesEcotone` MUST be called with the new Ecotone attributes. + +`setL1BlockValuesEcotone` uses a tightly packed encoding for its parameters, which is described in +[L1 Attributes Deposited Transaction Calldata](../deposits.md#l1-attributes-deposited-transaction-calldata). diff --git a/specs/protocol/ecotone/overview.md b/specs/protocol/ecotone/overview.md new file mode 100644 index 0000000..8bcc8a5 --- /dev/null +++ b/specs/protocol/ecotone/overview.md @@ -0,0 +1,41 @@ +# Ecotone Network Upgrade + + + +**Table of Contents** + +- [Execution Layer](#execution-layer) +- [Consensus Layer](#consensus-layer) + + + +The Ecotone upgrade contains the Dencun upgrade from L1, and adopts EIP-4844 blobs for data-availability. + +## Execution Layer + +- Cancun (Execution Layer): + - [EIP-1153: Transient storage opcodes](https://eips.ethereum.org/EIPS/eip-1153) + - [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844) + - [Blob transactions are disabled](../exec-engine.md#ecotone-disable-blob-transactions) + - [EIP-4788: Beacon block root in the EVM](https://eips.ethereum.org/EIPS/eip-4788) + - [The L1 beacon block root is embedded into L2](../exec-engine.md#ecotone-beacon-block-root) + - [The Beacon roots contract deployment is automated](../derivation.md#ecotone-beacon-block-roots-contract-deployment-eip-4788) + - [EIP-5656: MCOPY - Memory copying instruction](https://eips.ethereum.org/EIPS/eip-5656) + - [EIP-6780: SELFDESTRUCT only in same transaction](https://eips.ethereum.org/EIPS/eip-6780) + - [EIP-7516: BLOBBASEFEE opcode](https://eips.ethereum.org/EIPS/eip-7516) + - [BLOBBASEFEE always pushes 1 onto the stack](../exec-engine.md#ecotone-disable-blob-transactions) +- Deneb (Consensus Layer): _not applicable to L2_ + - [EIP-7044: Perpetually Valid Signed Voluntary Exits](https://eips.ethereum.org/EIPS/eip-7044) + - [EIP-7045: Increase Max Attestation Inclusion Slot](https://eips.ethereum.org/EIPS/eip-7045) + - [EIP-7514: Add Max Epoch Churn Limit](https://eips.ethereum.org/EIPS/eip-7514) + +## Consensus Layer + +[retrieval]: ../derivation.md#ecotone-blob-retrieval +[predeploy]: ./l1-attributes.md#ecotone-l1block-upgrade + +- Blobs Data Availability: support blobs DA the [L1 Data-retrieval stage][retrieval]. +- Rollup fee update: support blobs DA in + [L1 Data Fee computation](../exec-engine.md#ecotone-l1-cost-fee-changes-eip-4844-da) +- Auto-upgrading and extension of the [L1 Attributes Predeployed Contract][predeploy] + (also known as `L1Block` predeploy) diff --git a/specs/protocol/mpt-migration/exec-engine.md b/specs/protocol/mpt-migration/exec-engine.md new file mode 100644 index 0000000..4d13b13 --- /dev/null +++ b/specs/protocol/mpt-migration/exec-engine.md @@ -0,0 +1,105 @@ +# L2 Execution Engine + + + +**Table of Contents** + +- [Overview](#overview) +- [Timestamp Activation](#timestamp-activation) +- [Historical RPC](#historical-rpc) + - [`eth_` namespace](#eth_-namespace) + - [`debug_` namespace](#debug_-namespace) +- [EVM Changes](#evm-changes) + - [Transition from ZK Trie to Merkle Patricia Trie](#transition-from-zk-trie-to-merkle-patricia-trie) + - [`SELFDESTRUCT` opcode](#selfdestruct-opcode) + - [`isSystemTransaction` field in `DepositTx` type](#issystemtransaction-field-in-deposittx-type) + - [Fee Distribution Process](#fee-distribution-process) + + + +[g-zktrie]: ../../glossary.md#zk-trie +[g-mpt]: ../../glossary.md#merkle-patricia-trie +[validator-system]: ../validator-v2/overview.md + +## Overview + +This upgrade changes the underlying trie structure of the execution client from the [ZK Trie][g-zktrie] to the +[Merkle Patricia Trie][g-mpt]. There are also subsequent changes to the EVM to enhance the compatibility with +Vanilla OP Stack. + +## Timestamp Activation + +Kroma MPT Migration upgrade, like other network upgrades, is activated at a timestamp. Changes to the L2 Block execution +rules are applied when the `L2 Timestamp >= activation time`. + +## Historical RPC + +Since the underlying trie structure is changed from the ZK Trie to the Merkle Patricia Trie, the historical RPC is used +for the RPC calls that are related to the historical data before the Kroma MPT Migration upgrade. The historical RPC +provides the historical data that is stored in the ZK Trie. The following endpoints will route the call to the +historical RPC if the requested block timestamp is before the activation time of the Kroma MPT Migration upgrade: + +### `eth_` namespace + +- `eth_getBalance` +- `eth_getProof` +- `eth_getCode` +- `eth_getStorageAt` +- `eth_call` +- `eth_estimateGas` +- `eth_createAccessList` +- `eth_getTransactionCount` + +### `debug_` namespace + +- `debug_traceBlockByNumber` +- `debug_traceBlockByHash` +- `debug_traceTransaction` + +## EVM Changes + +### Transition from ZK Trie to Merkle Patricia Trie + +The underlying trie structure of the execution client is changed from the ZK Trie to the Merkle Patricia Trie. This +enhances the performance of the execution client, and reduces the operational cost of maintaining zkEVM circuits by +enabling the proving scheme transition to [zkVM](../../zk-fault-proof/zkvm-prover.md). + +### `SELFDESTRUCT` opcode + +The `SELFDESTRUCT` opcode was regarded as invalid opcode, since zkEVM proving system used in ZK fault proof cannot prove +the self-destruct operation. However, with the transition to zkVM, the `SELFDESTRUCT` opcode is now enabled, following +rules that are defined at [EIP-6780]. + +[EIP-6780]: https://eips.ethereum.org/EIPS/eip-6780 + +### `isSystemTransaction` field in `DepositTx` type + +In the previous version of the protocol, the `isSystemTransaction` boolean was removed. To enhance the compatibility +with vanilla OP Stack, the `isSystemTransaction` boolean is re-enabled. + +However, since `isSystemTransaction` was disabled as in the [Regolith upgrade](../regolith/overview.md), system +transactions remain to use the same gas accounting rules as regular deposits. + +### Fee Distribution Process + +The fee distribution process is updated to be compatible with OP Stack. Previously, the fee distribution process was +defined to support robustness of validator system. + +| Vault | Address | Amount | +|------------------------|----------------------------------------------|-----------------------------------------------------------------------| +| `ProtocolVault` | `0x4200000000000000000000000000000000000006` | `(base_fee + priority_fee) * (10000 - validatorRewardScalar) / 10000` | +| `L1FeeVault` | `0x4200000000000000000000000000000000000007` | `l1_cost` | +| `ValidatorRewardVault` | `0x4200000000000000000000000000000000000008` | `(base_fee + priority_fee) * validatorRewardScalar / 10000` | + +However, with transition to [KRO-based validator system][validator-system], validators are now getting KRO rewards, +and `validatorRewardScalar` was set to 0. After Kroma MPT Migration upgrade, the fee distribution process is updated +as follows: + +| Vault | Address | Amount | +|---------------------|----------------------------------------------|----------------| +| `SequencerFeeVault` | `0x4200000000000000000000000000000000000011` | `priority_fee` | +| `BaseFeeVault` | `0x4200000000000000000000000000000000000019` | `base_fee` | +| `L1FeeVault` | `0x420000000000000000000000000000000000001a` | `l1_cost` | + +Note that after Kroma MPT hard fork, the block fee-recipient (a.k.a. coinbase address) is set to the Sequencer Fee Vault +address. diff --git a/specs/protocol/mpt-migration/overview.md b/specs/protocol/mpt-migration/overview.md new file mode 100644 index 0000000..7c505cc --- /dev/null +++ b/specs/protocol/mpt-migration/overview.md @@ -0,0 +1,21 @@ +# Kroma MPT Migration + + + +**Table of Contents** + +- [Execution Layer](#execution-layer) +- [Smart Contracts](#smart-contracts) + + + +## Execution Layer + +- [Transition from ZK Trie to MPT](./exec-engine.md#transition-from-zk-trie-to-mpt) +- [Enable `SELFDESTRUCT` opcode](./exec-engine.md#selfdestruct-opcode) +- [Revive `isSystemTransaction` field at `DepositTx`](./exec-engine.md#issystemtransaction-boolean) +- [Modify Fee distribution process](./exec-engine.md#fee-distribution-process) + +## Smart Contracts + +- [Change Predeploys addresses](./predeploys.md) diff --git a/specs/protocol/mpt-migration/predeploys.md b/specs/protocol/mpt-migration/predeploys.md new file mode 100644 index 0000000..cd492fe --- /dev/null +++ b/specs/protocol/mpt-migration/predeploys.md @@ -0,0 +1,49 @@ +# Predeploys + + + +**Table of Contents** + +- [Changes on Predeploys](#changes-on-predeploys) + - [L1Block](#l1block) + - [L1FeeVault](#l1feevault) + - [ProtocolVault](#protocolvault) + - [SequencerFeeVault](#sequencerfeevault) + - [BaseFeeVault](#basefeevault) + + + +## Changes on Predeploys + +### L1Block + +Following the Kroma MPT upgrade, the calldata to set values in the `L1Block` predeploy is updated to +exclude the `validatorRewardScalar`. Now the calldata is as follows: + +```text +baseFeeScalar ++ blobBaseFeeScalar ++ sequenceNumber ++ timestamp ++ blockNumber ++ baseFee ++ blobBaseFee ++ blockHash ++ batcherHash +``` + +Also, the address of `L1Block` is changed from `0x4200000000000000000000000000000000000002` to +`0x4200000000000000000000000000000000000015`. The original address is now deprecated and not used after the Kroma MPT +hard fork. + +### L1FeeVault + +The address of `L1FeeVault` is changed from `0x4200000000000000000000000000000000000007` to +`0x420000000000000000000000000000000000001a`. The original address is now deprecated and not used after the Kroma MPT +hard fork. + +### ProtocolVault + +The `ProtocolVault` is now deprecated and not used after the Kroma MPT hard fork. + +### SequencerFeeVault + +The new predeploy `SequencerFeeVault` is introduced with the address `0x4200000000000000000000000000000000000011` after +the Kroma MPT hard fork. + +### BaseFeeVault + +The new predeploy `BaseFeeVault` is introduced with the address `0x4200000000000000000000000000000000000019` after +the Kroma MPT hard fork. diff --git a/specs/protocol/regolith/overview.md b/specs/protocol/regolith/overview.md new file mode 100644 index 0000000..e4e68ff --- /dev/null +++ b/specs/protocol/regolith/overview.md @@ -0,0 +1,40 @@ +# Regolith + + + +**Table of Contents** + +- [Overview](#overview) + + + +[deposits]: ../deposits.md +[exec-engine]: ../exec-engine.md + +## Overview + +The Regolith upgrade, named after a material best described as "deposited dust on top of a layer of bedrock", +implements minor changes to deposit processing, based on reports of the Sherlock Audit-contest and findings in +the Bedrock Optimism Goerli testnet. + +Regolith has been integrated and activated from the genesis block on Kroma. + +Summary of changes: + +- The `isSystemTx` boolean is disabled, system transactions now use the same gas accounting rules as regular deposits. +- The actual deposit gas-usage is recorded in the receipt of the deposit transaction, + and subtracted from the L2 block gas-pool. + Unused gas of deposits is not refunded with ETH however, as it is burned on L1. +- The `nonce` value of the deposit sender account, before the transaction state-transition, is recorded in a new + optional field (`depositNonce`), extending the transaction receipt (i.e. not present in pre-Regolith receipts). +- The recorded deposit `nonce` is used to correct the transaction and receipt metadata in RPC responses, + including the `contractAddress` field of deposits that deploy contracts. +- The `gas` and `depositNonce` data is committed to as part of the consensus-representation of the receipt, + enabling the data to be safely synced between independent L2 nodes. +- The L1-cost function was corrected to more closely match pre-Bedrock behavior. + +The [deposit specification][deposits] specifies the deposit changes of the Regolith upgrade in more detail. +The [execution engine specification][exec-engine] specifies the L1 cost function difference. + +The Regolith upgrade uses a _L2 block-timestamp_ activation-rule, and is specified in both the +rollup-node (`regolith_time`) and execution engine (`config.regolithTime`). diff --git a/specs/protocol/validation.md b/specs/protocol/validation.md index 632ede8..1a6327b 100644 --- a/specs/protocol/validation.md +++ b/specs/protocol/validation.md @@ -122,7 +122,7 @@ where: L2toL1MessagePasser's storage root directly, thus reducing the verification cost of withdrawals on L1. The height of the block where the output is submitted has been delayed by one. Note that `next_block_hash` is deprecated -and not used in the construction of the output root after Kroma MPT migration fork. +and not used in the construction of the output root after [Kroma MPT migration fork](./mpt-migration/overview.md). ## L2 Output Oracle Smart Contract