diff --git a/specs/fjord/deposits.md b/specs/fjord/deposits.md new file mode 100644 index 000000000..4c6884f7a --- /dev/null +++ b/specs/fjord/deposits.md @@ -0,0 +1,93 @@ +# Deposits + + + +**Table of Contents** + +- [L1 Attributes Deposited Transaction](#l1-attributes-deposited-transaction) + - [L1 Attributes Deposited Transaction Calldata](#l1-attributes-deposited-transaction-calldata) + - [L1 Attributes - Fjord](#l1-attributes---fjord) +- [Special Accounts on L2](#special-accounts-on-l2) + - [L1 Attributes Predeployed Contract](#l1-attributes-predeployed-contract) + - [Fjord L1Block upgrade](#fjord-l1block-upgrade) + + + +## L1 Attributes Deposited Transaction + +### L1 Attributes Deposited Transaction Calldata + +#### L1 Attributes - Fjord + +On the Fjord activation block, and if Fjord is not activated at Genesis, +the L1 Attributes Transaction includes a call to `setL1BlockValuesEcotone()` +because the L1 Attributes transaction precedes the [Fjord Upgrade Transactions][fjord-upgrade-txs], +meaning that `setL1BlockValuesFjord` is not guaranteed to exist yet. + +Every subsequent L1 Attributes transaction should include a call to the `setL1BlockValuesFjord()` function. +The input args are no longer ABI encoded function parameters, +but are instead packed into 5 32-byte aligned segments and one 12-byte segment (starting after the function selector). +Each signed and 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: + +[fjord-upgrade-txs]: derivation.md#fjord + +| Input arg | Type | Calldata bytes | Segment | +|-------------------|---------|----------------|---------| +| {0x850c16d8} | | 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 | +| l1CostIntercept | int32 | 164-167 | 6 | +| l1CostFastlzCoef | int32 | 168-171 | | +| l1CostTxSizeCoef | int32 | 172-175 | | + +Total calldata length MUST be exactly 176 bytes. + +In the first L2 block after the Fjord activation block, the Fjord L1 attributes are first used. + +The pre-Fjord values are migrated over 1:1. +Blocks after the Fjord activation block contain all pre-Fjord values 1:1, +and also set the following new attributes: + +- The `l1CostIntercept` is set to `0`. +- The `l1CostFastlzCoef` is set to `0`. +- The `l1CostTxSizeCoef` is set to `1e6`. + +## Special Accounts on L2 + +### L1 Attributes Predeployed Contract + +- With the Fjord upgrade, the predeploy additionally stores: + - `l1CostIntercept` (`int32`): system configurable to set the L1 cost formula intercept + - `l1CostFastlzCoef` (`int32`): system configurable to set the L1 cost formula FastLZ coefficient + - `l1CostTxSizeCoef` (`int32`): system configurable to set the L1 cost formula transaction size coefficient + +#### Fjord L1Block upgrade + +The L1 Attributes Predeployed contract, `L1Block.sol`, is upgraded as part of the Fjord upgrade. +The version is incremented to `1.3.0`, and one existing slot begins to store additional data: + +- `l1CostIntercept` (`int32`): system configurable to set the L1 cost formula intercept +- `l1CostFastlzCoef` (`int32`): system configurable to set the L1 cost formula FastLZ coefficient +- `l1CostTxSizeCoef` (`int32`): system configurable to set the L1 cost formula transaction size coefficient + +The function called by the L1 attributes transaction depends on the network upgrade: + +- Before the Fjord activation: + - `setL1BlockValuesEcotone` is called, following the pre-Fjord L1 attributes rules. +- At the Fjord activation block: + - `setL1BlockValuesEcotone` function MUST be called, except if activated at genesis. + The contract is upgraded later in this block, to support `setL1BlockValuesFjord`. +- After the Fjord activation: + - `setL1BlockValuesEcotone` function is deprecated and MUST never be called. + - `setL1BlockValuesFjord` MUST be called with the new Fjord attributes. + +`setL1BlockValuesFjord` uses a tightly packed encoding for its parameters, which is described in +[L1 Attributes - Fjord](#l1-attributes---fjord). diff --git a/specs/fjord/derivation.md b/specs/fjord/derivation.md new file mode 100644 index 000000000..d1189d9fe --- /dev/null +++ b/specs/fjord/derivation.md @@ -0,0 +1,206 @@ +# Deriving Payload Attributes + + + +**Table of Contents** + +- [Deriving the Transaction List](#deriving-the-transaction-list) + - [Network upgrade automation transactions](#network-upgrade-automation-transactions) + - [Fjord](#fjord) + - [L1Block Deployment - Fjord](#l1block-deployment---fjord) + - [GasPriceOracle Deployment - Fjord](#gaspriceoracle-deployment---fjord) + - [L1Block Proxy Update - Fjord](#l1block-proxy-update---fjord) + - [GasPriceOracle Proxy Update - Fjord](#gaspriceoracle-proxy-update---fjord) + - [GasPriceOracle Enable Fjord](#gaspriceoracle-enable-fjord) + + + +## Deriving the Transaction List + +### Network upgrade automation transactions + +#### Fjord + +The Fjord hardfork activation block, contains the following transactions in this order: + +- L1 Attributes Transaction, using the pre-Fjord `setL1BlockValuesEcotone` +- User deposits from L1 +- Network Upgrade Transactions + - L1Block deployment + - GasPriceOracle deployment + - Update L1Block Proxy ERC-1967 Implementation Slot + - Update GasPriceOracle Proxy ERC-1967 Implementation Slot + - GasPriceOracle Enable Fjord + +To not modify or interrupt the system behavior around gas computation, this block will not include any sequenced +transactions by setting `noTxPool: true`. + +##### L1Block Deployment - Fjord + +The `L1Block` contract is upgraded to store the new Fjord Fast LZ parameters. + +To perform this upgrade, a deposit transaction is derived with the following attributes: + +- `from`: `0x4210000000000000000000000000000000000002` +- `to`: `null` +- `mint`: `0` +- `value`: `0` +- `gasLimit`: `420,000` +- `data`: `0x60806040523...` ([full bytecode](../static/bytecode/fjord-l1-block-deployment.txt)) +- `sourceHash`: `0x402f75bf100f605f36c2e2b8d5544a483159e26f467a9a555c87c125e7ab09f3`, + computed with the "Upgrade-deposited" type, with `intent = "Fjord: L1 Block Deployment" + +This results in the Fjord L1Block contract being deployed to `0xa919894851548179A0750865e7974DA599C0Fac7`, to verify: + +```bash +cast compute-address --nonce=0 0x4210000000000000000000000000000000000002 +Computed Address: 0xa919894851548179A0750865e7974DA599C0Fac7 +``` + +Verify `sourceHash`: + +```bash +cast keccak $(cast concat-hex 0x0000000000000000000000000000000000000000000000000000000000000002 $(cast keccak "Fjord: L1 Block Deployment")) +# 0x402f75bf100f605f36c2e2b8d5544a483159e26f467a9a555c87c125e7ab09f3 +``` + +Verify `data`: + +```bash +git checkout TODO (update once merged) +pnpm clean && pnpm install && pnpm build +jq -r ".bytecode.object" packages/contracts-bedrock/forge-artifacts/L1Block.sol/L1Block.json +``` + +This transaction MUST deploy a contract with the following code hash +`0x12e89c50902af815d85608f9a2a35579a74e9491077b94211c96f79ef265bf9c`. + +##### GasPriceOracle Deployment - Fjord + +The `GasPriceOracle` contract is upgraded to support the new Fjord L1 data fee computation. Post fork this contract +will use FastLZ to compute the L1 data fee. + +To perform this upgrade, a deposit transaction is derived with the following attributes: + +- `from`: `0x4210000000000000000000000000000000000003` +- `to`: `null`, +- `mint`: `0` +- `value`: `0` +- `gasLimit`: `1,450,000` +- `data`: `0x60806040523...` ([full bytecode](../static/bytecode/fjord-gas-price-oracle-deployment.txt)) +- `sourceHash`: `0x86122c533fdcb89b16d8713174625e44578a89751d96c098ec19ab40a51a8ea3` + computed with the "Upgrade-deposited" type, with `intent = "Fjord: Gas Price Oracle Deployment" + +This results in the Fjord GasPriceOracle contract being deployed to `0xFf256497D61dcd71a9e9Ff43967C13fdE1F72D12`, +to verify: + +```bash +cast compute-address --nonce=0 0x4210000000000000000000000000000000000003 +Computed Address: 0xFf256497D61dcd71a9e9Ff43967C13fdE1F72D12 +``` + +Verify `sourceHash`: + +```bash +❯ cast keccak $(cast concat-hex 0x0000000000000000000000000000000000000000000000000000000000000002 $(cast keccak "Fjord: Gas Price Oracle Deployment")) +# 0x86122c533fdcb89b16d8713174625e44578a89751d96c098ec19ab40a51a8ea3 +``` + +Verify `data`: + +```bash +git checkout TODO (update once merged) +pnpm clean && pnpm install && pnpm build +jq -r ".bytecode.object" packages/contracts-bedrock/forge-artifacts/GasPriceOracle.sol/GasPriceOracle.json +``` + +This transaction MUST deploy a contract with the following code hash +`0xcb82de8a527fee307214950192bf0ff5b2701c6b6eda2fbd025cf6d4075fbe38`. + +##### L1Block Proxy Update - Fjord + +This transaction updates the L1Block Proxy ERC-1967 implementation slot to point to the new L1Block deployment. + +A deposit transaction is derived with the following attributes: + +- `from`: `0x0000000000000000000000000000000000000000` +- `to`: `0x4200000000000000000000000000000000000015` (L1Block Proxy) +- `mint`: `0` +- `value`: `0` +- `gasLimit`: `50,000` +- `data`: `0x3659cfe6000000000000000000000000a919894851548179a0750865e7974da599c0fac7` +- `sourceHash`: `0x0fefb8cb7f44b866e21a59f647424cee3096de3475e252eb3b79fa3f733cee2d` + computed with the "Upgrade-deposited" type, with `intent = "Fjord: L1 Block Proxy Update" + +Verify data: + +```bash +cast concat-hex $(cast sig "upgradeTo(address)") $(cast abi-encode "upgradeTo(address)" 0xa919894851548179A0750865e7974DA599C0Fac7) +0x3659cfe6000000000000000000000000a919894851548179a0750865e7974da599c0fac7 +``` + +Verify `sourceHash`: + +```bash +cast keccak $(cast concat-hex 0x0000000000000000000000000000000000000000000000000000000000000002 $(cast keccak "Fjord: L1 Block Proxy Update")) +# 0x0fefb8cb7f44b866e21a59f647424cee3096de3475e252eb3b79fa3f733cee2d +``` + +##### GasPriceOracle Proxy Update - Fjord + +This transaction updates the GasPriceOracle Proxy ERC-1967 implementation slot to point to the new GasPriceOracle +deployment. + +A deposit transaction is derived with the following attributes: + +- `from`: `0x0000000000000000000000000000000000000000` +- `to`: `0x420000000000000000000000000000000000000F` (Gas Price Oracle Proxy) +- `mint`: `0` +- `value`: `0` +- `gasLimit`: `50,000` +- `data`: `0x3659cfe6000000000000000000000000ff256497d61dcd71a9e9ff43967c13fde1f72d12` +- `sourceHash`: `0x1e6bb0c28bfab3dc9b36ffb0f721f00d6937f33577606325692db0965a7d58c6` + computed with the "Upgrade-deposited" type, with `intent = "Fjord: Gas Price Oracle Proxy Update"` + +Verify data: + +```bash +cast concat-hex $(cast sig "upgradeTo(address)") $(cast abi-encode "upgradeTo(address)" 0xFf256497D61dcd71a9e9Ff43967C13fdE1F72D12) +0x3659cfe6000000000000000000000000ff256497d61dcd71a9e9ff43967c13fde1f72d12 +``` + +Verify `sourceHash`: + +```bash +cast keccak $(cast concat-hex 0x0000000000000000000000000000000000000000000000000000000000000002 $(cast keccak "Fjord: Gas Price Oracle Proxy Update")) +# 0x1e6bb0c28bfab3dc9b36ffb0f721f00d6937f33577606325692db0965a7d58c6 +``` + +##### GasPriceOracle Enable Fjord + +This transaction informs the GasPriceOracle to start using the Fjord gas calculation formula. + +A deposit transaction is derived with the following attributes: + +- `from`: `0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001` (Depositer Account) +- `to`: `0x420000000000000000000000000000000000000F` (Gas Price Oracle Proxy) +- `mint`: `0` +- `value`: `0` +- `gasLimit`: `80,000` +- `data`: `0x8e98b106` +- `sourceHash`: `0xbac7bb0d5961cad209a345408b0280a0d4686b1b20665e1b0f9cdafd73b19b6b`, + computed with the "Upgrade-deposited" type, with `intent = "Fjord: Gas Price Oracle Set Fjord" + +Verify data: + +```bash +cast sig "setFjord()" +0x8e98b106 +``` + +Verify `sourceHash`: + +```bash +cast keccak $(cast concat-hex 0x0000000000000000000000000000000000000000000000000000000000000002 $(cast keccak "Fjord: Gas Price Oracle Set Fjord")) +# 0xbac7bb0d5961cad209a345408b0280a0d4686b1b20665e1b0f9cdafd73b19b6b +``` diff --git a/specs/fjord/exec-engine.md b/specs/fjord/exec-engine.md new file mode 100644 index 000000000..78c4b0c68 --- /dev/null +++ b/specs/fjord/exec-engine.md @@ -0,0 +1,108 @@ +# L2 Execution Engine + + + +**Table of Contents** + +- [Fees](#fees) + - [L1-Cost fees (L1 Fee Vault)](#l1-cost-fees-l1-fee-vault) + - [Fjord L1-Cost fee changes (FastLZ estimator)](#fjord-l1-cost-fee-changes-fastlz-estimator) + - [L1-Cost linear regression details](#l1-cost-linear-regression-details) + + + +## Fees + +### L1-Cost fees (L1 Fee Vault) + +#### Fjord L1-Cost fee changes (FastLZ estimator) + +Fjord updates the L1 cost calculation function to use a FastLZ-based compression estimator. +The L1 cost is computed as: + +```pseudocode +l1FeeScaled = l1BaseFeeScalar*l1BaseFee*16 + l1BlobFeeScalar*l1BlobBaseFee +l1CostSigned = (intercept + fastlzCoef*fastlzSize + txSizeCoef*txSize) * l1FeeScaled / 1e12 +l1Cost = uint256(max(0, l1CostSigned)) +``` + +| Input arg | Type | Description | +|-------------------|-----------|-------------------------------------------------------------------| +| `l1BaseFee` | `uint256` | L1 base fee of the latest L1 origin registered in the L2 chain | +| `l1BlobBaseFee` | `uint256` | Blob gas price of the latest L1 origin registered in the L2 chain | +| `fastlzSize` | `uint256` | Length of the FastLZ-compressed RLP-encoded signed tx | +| `txSize` | `uint256` | Length of uncompressed RLP-encoded signed tx | +| `l1BaseFeeScalar` | `uint32` | L1 base fee scalar, scaled by `1e6` | +| `l1BlobFeeScalar` | `uint32` | L1 blob fee scalar, scaled by `1e6` | +| `intercept` | `int32` | Intercept constant, scaled by `1e6` (can be negative) | +| `fastlzCoef` | `int32` | FastLZ coefficient, scaled by `1e6` (can be negative) | +| `txSizeCoef` | `int32` | Transaction size coefficient, scaled by `1e6` (can be negative) | + +Where: + +- the `l1CostSigned` calculation is an unlimited precision signed integer computation, with the result in Wei and + having `int256` range. + +- the final `l1Cost` computation is an unlimited precision unsigned integer computation, with the result in Wei and + having `uint256` range. + +##### L1-Cost linear regression details + +The `intercept`, `fastlzCoef`, and `txSizeCoef` constants are calculated by linear regression using a dataset +of previous L2 transactions. The dataset is generated by iterating over all transactions in a given time range, and +performing the following actions. For each transaction: + +1. Calculate the RLP-encoded transaction payload. Record the length of this payload as `txSize`. +2. Compress the payload using FastLZ. Record the length of the compressed payload as `fastlzSize`. +3. Compress the payload using a "best estimate" compression, defined as: + +- Create two zlib streams, both using the maximum compression level. +- Bootstrap one of the streams with at least 64kb of transaction data (after compression). +- Write each transaction to both streams (flushing after each write), and record the size increase + of the larger buffer as `bestEstimateSize`. +- Each time the larger buffer grows larger than 128kb, empty the stream and swap the buffers. + +Once this dataset is generated, a linear regression can be calculated using the `bestEstimateSize` as +the dependent variable and `fastlzSize` and `txSize` as the independent variables. + +The following Python code can be used to calculate the linear regression: + +```python +import numpy as np +from sklearn.linear_model import LinearRegression + +# Dataset format is: +# data = [record...] (one or more records, concatenated) +# record = bestEstimateSize ++ fastlzSize ++ txSize +# bestEstimateSize = little-endian uint32 +# fastlzSize = little-endian uint32 +# txSize = little-endian uint32 + +dt = np.dtype([('best', ' + +**Table of Contents** + +- [GasPriceOracle](#gaspriceoracle) + + + +## GasPriceOracle + +Following the Fjord upgrade, the values used for L1 fee computation are: + +- baseFeeScalar +- blobBaseFeeScalar +- costIntercept +- costFastlzCoef +- costTxSizeCoef +- decimals + +These values are managed by the `SystemConfig` contract on the L1. The`decimals` remains hardcoded +to 6. diff --git a/specs/fjord/system_config.md b/specs/fjord/system_config.md new file mode 100644 index 000000000..1c919aa3c --- /dev/null +++ b/specs/fjord/system_config.md @@ -0,0 +1,54 @@ +# System Config + + + +**Table of Contents** + +- [System config contents (version 0)](#system-config-contents-version-0) + - [Scalars](#scalars) + - [Fjord `scalar` (`uint256`) change](#fjord-scalar-uint256-change) + + + +## System config contents (version 0) + +### Scalars + +#### Fjord `scalar` (`uint256`) change + +After Fjord activation, the `scalar` attribute encodes additional scalar information, in a versioned encoding scheme. + +The `scalar` is encoded as big-endian `uint256`, interpreted as `bytes32`, and composed as following: + +\*Byte ranges are indicated with `[` (inclusive) and `)` (exclusive). + +- `0`: scalar-version byte +- `[1, 32)`: depending scalar-version: + - Scalar-version `0`: + - `[1, 28)`: padding, should be zero. + - `[28, 32)`: big-endian `uint32`, encoding the L1-fee `baseFeeScalar` + - This version implies the L1-fee `blobBaseFeeScalar` is set to 0. + - In the event there are non-zero bytes in the padding area, `baseFeeScalar` must be set to MaxUint32. + - This version is compatible with the pre-Ecotone `scalar` value (assuming a `uint32` range). + - This version implies that `costIntercept` and `costFastlzCoef` are set to 0, and `costTxSizeCoef` is set to `1e6`. + - Scalar-version `1`: + - `[1, 24)`: padding, must be zero. + - `[24, 28)`: big-endian `uint32`, encoding the `blobBaseFeeScalar` + - `[28, 32)`: big-endian `uint32`, encoding the `baseFeeScalar` + - This version is meant to configure the EIP-4844 blob fee component, once blobs are used for data-availability. + - This version implies that `costIntercept` and `costFastlzCoef` are set to 0, and `costTxSizeCoef` is set to `1e6`. + - Scalar-version `2`: + - `[1, 12)`: padding, should be zero. + - `[12, 16)`: big-endian `int32`, encoding the `costTxSizeCoef` + - `[16, 20)`: big-endian `int32`, encoding the `costFastlzCoef` + - `[20, 24)`: big-endian `int32`, encoding the `costIntercept` + - `[24, 28)`: big-endian `uint32`, encoding the `blobBaseFeeScalar` + - `[28, 32)`: big-endian `uint32`, encoding the `baseFeeScalar` + - Other scalar-version values: unrecognized. + OP-Stack forks are recommended to utilize the `>= 128` scalar-version range and document their `scalar` encoding. + +Invalid and unrecognized scalar event-data should be ignored, +and the last valid configuration should continue to be utilized. + +The scalar values are incorporated into the L2 through the +[Fjord L1 attributes deposit transaction calldata](deposits.md#l1-attributes---fjord). diff --git a/specs/protocol/deposits.md b/specs/protocol/deposits.md index 3bb0981f3..4ab2ef321 100644 --- a/specs/protocol/deposits.md +++ b/specs/protocol/deposits.md @@ -312,49 +312,6 @@ 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 - Fjord - -On the Fjord activation block, and if Fjord is not activated at Genesis, -the L1 Attributes Transaction includes a call to `setL1BlockValuesEcotone()` -because the L1 Attributes transaction precedes the [Fjord Upgrade Transactions][fjord-upgrade-txs], -meaning that `setL1BlockValuesFjord` is not guaranteed to exist yet. - -Every subsequent L1 Attributes transaction should include a call to the `setL1BlockValuesFjord()` function. -The input args are no longer ABI encoded function parameters, -but are instead packed into 5 32-byte aligned segments and one 12-byte segment (starting after the function selector). -Each signed and 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: - -[fjord-upgrade-txs]: derivation.md#fjord - -| Input arg | Type | Calldata bytes | Segment | -|-------------------|---------|----------------|---------| -| {0x850c16d8} | | 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 | -| l1CostIntercept | int32 | 164-167 | 6 | -| l1CostFastlzCoef | int32 | 168-171 | | -| l1CostTxSizeCoef | int32 | 172-175 | | - -Total calldata length MUST be exactly 176 bytes. - -In the first L2 block after the Fjord activation block, the Fjord L1 attributes are first used. - -The pre-Fjord values are migrated over 1:1. -Blocks after the Fjord activation block contain all pre-Fjord values 1:1, -and also set the following new attributes: - -- The `l1CostIntercept` is set to `0`. -- The `l1CostFastlzCoef` is set to `0`. -- The `l1CostTxSizeCoef` is set to `1e6`. - ## Special Accounts on L2 The L1 attributes deposit transaction involves two special purpose accounts: @@ -398,10 +355,6 @@ The predeploy stores the following values: - `blobBaseFee` (`uint256`) - `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 -- With the Fjord upgrade, the predeploy additionally stores: - - `l1CostIntercept` (`int32`): system configurable to set the L1 cost formula intercept - - `l1CostFastlzCoef` (`int32`): system configurable to set the L1 cost formula FastLZ coefficient - - `l1CostTxSizeCoef` (`int32`): system configurable to set the L1 cost formula transaction size coefficient The `overhead` and `scalar` values can continue to be accessed after the Ecotone activation block, but no longer have any effect on system operation. @@ -450,29 +403,6 @@ The function called by the L1 attributes transaction depends on the network upgr `setL1BlockValuesEcotone` uses a tightly packed encoding for its parameters, which is described in [L1 Attributes - Ecotone](#l1-attributes---ecotone). -#### Fjord L1Block upgrade - -The L1 Attributes Predeployed contract, `L1Block.sol`, is upgraded as part of the Fjord upgrade. -The version is incremented to `1.3.0`, and one existing slot begins to store additional data: - -- `l1CostIntercept` (`int32`): system configurable to set the L1 cost formula intercept -- `l1CostFastlzCoef` (`int32`): system configurable to set the L1 cost formula FastLZ coefficient -- `l1CostTxSizeCoef` (`int32`): system configurable to set the L1 cost formula transaction size coefficient - -The function called by the L1 attributes transaction depends on the network upgrade: - -- Before the Fjord activation: - - `setL1BlockValuesEcotone` is called, following the pre-Fjord L1 attributes rules. -- At the Fjord activation block: - - `setL1BlockValuesEcotone` function MUST be called, except if activated at genesis. - The contract is upgraded later in this block, to support `setL1BlockValuesFjord`. -- After the Fjord activation: - - `setL1BlockValuesEcotone` function is deprecated and MUST never be called. - - `setL1BlockValuesFjord` MUST be called with the new Fjord attributes. - -`setL1BlockValuesFjord` uses a tightly packed encoding for its parameters, which is described in -[L1 Attributes - Fjord](#l1-attributes---fjord). - ## User-Deposited Transactions [user-deposited]: #user-deposited-transactions diff --git a/specs/protocol/derivation.md b/specs/protocol/derivation.md index 602e7dae2..f26724961 100644 --- a/specs/protocol/derivation.md +++ b/specs/protocol/derivation.md @@ -1345,192 +1345,6 @@ cast keccak $(cast concat-hex 0x000000000000000000000000000000000000000000000000 [EIP-4788]: https://eips.ethereum.org/EIPS/eip-4788 [EIP-155]: https://eips.ethereum.org/EIPS/eip-155 -#### Fjord - -The Fjord hardfork activation block, contains the following transactions in this order: - -- L1 Attributes Transaction, using the pre-Fjord `setL1BlockValuesEcotone` -- User deposits from L1 -- Network Upgrade Transactions - - L1Block deployment - - GasPriceOracle deployment - - Update L1Block Proxy ERC-1967 Implementation Slot - - Update GasPriceOracle Proxy ERC-1967 Implementation Slot - - GasPriceOracle Enable Fjord - -To not modify or interrupt the system behavior around gas computation, this block will not include any sequenced -transactions by setting `noTxPool: true`. - -##### L1Block Deployment - Fjord - -The `L1Block` contract is upgraded to store the new Fjord Fast LZ parameters. - -To perform this upgrade, a deposit transaction is derived with the following attributes: - -- `from`: `0x4210000000000000000000000000000000000002` -- `to`: `null` -- `mint`: `0` -- `value`: `0` -- `gasLimit`: `420,000` -- `data`: `0x60806040523...` ([full bytecode](../static/bytecode/fjord-l1-block-deployment.txt)) -- `sourceHash`: `0x402f75bf100f605f36c2e2b8d5544a483159e26f467a9a555c87c125e7ab09f3`, - computed with the "Upgrade-deposited" type, with `intent = "Fjord: L1 Block Deployment" - -This results in the Fjord L1Block contract being deployed to `0xa919894851548179A0750865e7974DA599C0Fac7`, to verify: - -```bash -cast compute-address --nonce=0 0x4210000000000000000000000000000000000002 -Computed Address: 0xa919894851548179A0750865e7974DA599C0Fac7 -``` - -Verify `sourceHash`: - -```bash -cast keccak $(cast concat-hex 0x0000000000000000000000000000000000000000000000000000000000000002 $(cast keccak "Fjord: L1 Block Deployment")) -# 0x402f75bf100f605f36c2e2b8d5544a483159e26f467a9a555c87c125e7ab09f3 -``` - -Verify `data`: - -```bash -git checkout TODO (update once merged) -pnpm clean && pnpm install && pnpm build -jq -r ".bytecode.object" packages/contracts-bedrock/forge-artifacts/L1Block.sol/L1Block.json -``` - -This transaction MUST deploy a contract with the following code hash -`0x12e89c50902af815d85608f9a2a35579a74e9491077b94211c96f79ef265bf9c`. - -##### GasPriceOracle Deployment - Fjord - -The `GasPriceOracle` contract is upgraded to support the new Fjord L1 data fee computation. Post fork this contract -will use FastLZ to compute the L1 data fee. - -To perform this upgrade, a deposit transaction is derived with the following attributes: - -- `from`: `0x4210000000000000000000000000000000000003` -- `to`: `null`, -- `mint`: `0` -- `value`: `0` -- `gasLimit`: `1,450,000` -- `data`: `0x60806040523...` ([full bytecode](../static/bytecode/fjord-gas-price-oracle-deployment.txt)) -- `sourceHash`: `0x86122c533fdcb89b16d8713174625e44578a89751d96c098ec19ab40a51a8ea3` - computed with the "Upgrade-deposited" type, with `intent = "Fjord: Gas Price Oracle Deployment" - -This results in the Fjord GasPriceOracle contract being deployed to `0xFf256497D61dcd71a9e9Ff43967C13fdE1F72D12`, -to verify: - -```bash -cast compute-address --nonce=0 0x4210000000000000000000000000000000000003 -Computed Address: 0xFf256497D61dcd71a9e9Ff43967C13fdE1F72D12 -``` - -Verify `sourceHash`: - -```bash -❯ cast keccak $(cast concat-hex 0x0000000000000000000000000000000000000000000000000000000000000002 $(cast keccak "Fjord: Gas Price Oracle Deployment")) -# 0x86122c533fdcb89b16d8713174625e44578a89751d96c098ec19ab40a51a8ea3 -``` - -Verify `data`: - -```bash -git checkout TODO (update once merged) -pnpm clean && pnpm install && pnpm build -jq -r ".bytecode.object" packages/contracts-bedrock/forge-artifacts/GasPriceOracle.sol/GasPriceOracle.json -``` - -This transaction MUST deploy a contract with the following code hash -`0xcb82de8a527fee307214950192bf0ff5b2701c6b6eda2fbd025cf6d4075fbe38`. - -##### L1Block Proxy Update - Fjord - -This transaction updates the L1Block Proxy ERC-1967 implementation slot to point to the new L1Block deployment. - -A deposit transaction is derived with the following attributes: - -- `from`: `0x0000000000000000000000000000000000000000` -- `to`: `0x4200000000000000000000000000000000000015` (L1Block Proxy) -- `mint`: `0` -- `value`: `0` -- `gasLimit`: `50,000` -- `data`: `0x3659cfe6000000000000000000000000a919894851548179a0750865e7974da599c0fac7` -- `sourceHash`: `0x0fefb8cb7f44b866e21a59f647424cee3096de3475e252eb3b79fa3f733cee2d` - computed with the "Upgrade-deposited" type, with `intent = "Fjord: L1 Block Proxy Update" - -Verify data: - -```bash -cast concat-hex $(cast sig "upgradeTo(address)") $(cast abi-encode "upgradeTo(address)" 0xa919894851548179A0750865e7974DA599C0Fac7) -0x3659cfe6000000000000000000000000a919894851548179a0750865e7974da599c0fac7 -``` - -Verify `sourceHash`: - -```bash -cast keccak $(cast concat-hex 0x0000000000000000000000000000000000000000000000000000000000000002 $(cast keccak "Fjord: L1 Block Proxy Update")) -# 0x0fefb8cb7f44b866e21a59f647424cee3096de3475e252eb3b79fa3f733cee2d -``` - -##### GasPriceOracle Proxy Update - Fjord - -This transaction updates the GasPriceOracle Proxy ERC-1967 implementation slot to point to the new GasPriceOracle -deployment. - -A deposit transaction is derived with the following attributes: - -- `from`: `0x0000000000000000000000000000000000000000` -- `to`: `0x420000000000000000000000000000000000000F` (Gas Price Oracle Proxy) -- `mint`: `0` -- `value`: `0` -- `gasLimit`: `50,000` -- `data`: `0x3659cfe6000000000000000000000000ff256497d61dcd71a9e9ff43967c13fde1f72d12` -- `sourceHash`: `0x1e6bb0c28bfab3dc9b36ffb0f721f00d6937f33577606325692db0965a7d58c6` - computed with the "Upgrade-deposited" type, with `intent = "Fjord: Gas Price Oracle Proxy Update"` - -Verify data: - -```bash -cast concat-hex $(cast sig "upgradeTo(address)") $(cast abi-encode "upgradeTo(address)" 0xFf256497D61dcd71a9e9Ff43967C13fdE1F72D12) -0x3659cfe6000000000000000000000000ff256497d61dcd71a9e9ff43967c13fde1f72d12 -``` - -Verify `sourceHash`: - -```bash -cast keccak $(cast concat-hex 0x0000000000000000000000000000000000000000000000000000000000000002 $(cast keccak "Fjord: Gas Price Oracle Proxy Update")) -# 0x1e6bb0c28bfab3dc9b36ffb0f721f00d6937f33577606325692db0965a7d58c6 -``` - -##### GasPriceOracle Enable Fjord - -This transaction informs the GasPriceOracle to start using the Fjord gas calculation formula. - -A deposit transaction is derived with the following attributes: - -- `from`: `0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001` (Depositer Account) -- `to`: `0x420000000000000000000000000000000000000F` (Gas Price Oracle Proxy) -- `mint`: `0` -- `value`: `0` -- `gasLimit`: `80,000` -- `data`: `0x8e98b106` -- `sourceHash`: `0xbac7bb0d5961cad209a345408b0280a0d4686b1b20665e1b0f9cdafd73b19b6b`, - computed with the "Upgrade-deposited" type, with `intent = "Fjord: Gas Price Oracle Set Fjord" - -Verify data: - -```bash -cast sig "setFjord()" -0x8e98b106 -``` - -Verify `sourceHash`: - -```bash -cast keccak $(cast concat-hex 0x0000000000000000000000000000000000000000000000000000000000000002 $(cast keccak "Fjord: Gas Price Oracle Set Fjord")) -# 0xbac7bb0d5961cad209a345408b0280a0d4686b1b20665e1b0f9cdafd73b19b6b -``` - ## Building Individual Payload Attributes [payload attributes]: #building-individual-payload-attributes diff --git a/specs/protocol/exec-engine.md b/specs/protocol/exec-engine.md index 126caffec..e9d92f14e 100644 --- a/specs/protocol/exec-engine.md +++ b/specs/protocol/exec-engine.md @@ -186,98 +186,6 @@ The two base fee values and their respective scalars can be accessed in two inte - l1BaseFeeScalar big-endian `uint32` slot `3` at offset `12` - l1BlobBaseFeeScalar big-endian `uint32` in slot `3` at offset `8` -#### Fjord L1-Cost fee changes (FastLZ estimator) - -Fjord updates the L1 cost calculation function to use a FastLZ-based compression estimator. -The L1 cost is computed as: - -```pseudocode -l1FeeScaled = l1BaseFeeScalar*l1BaseFee*16 + l1BlobFeeScalar*l1BlobBaseFee -l1CostSigned = (intercept + fastlzCoef*fastlzSize + txSizeCoef*txSize) * l1FeeScaled / 1e12 -l1Cost = uint256(max(0, l1CostSigned)) -``` - -| Input arg | Type | Description | -|-------------------|-----------|-------------------------------------------------------------------| -| `l1BaseFee` | `uint256` | L1 base fee of the latest L1 origin registered in the L2 chain | -| `l1BlobBaseFee` | `uint256` | Blob gas price of the latest L1 origin registered in the L2 chain | -| `fastlzSize` | `uint256` | Length of the FastLZ-compressed RLP-encoded signed tx | -| `txSize` | `uint256` | Length of uncompressed RLP-encoded signed tx | -| `l1BaseFeeScalar` | `uint32` | L1 base fee scalar, scaled by `1e6` | -| `l1BlobFeeScalar` | `uint32` | L1 blob fee scalar, scaled by `1e6` | -| `intercept` | `int32` | Intercept constant, scaled by `1e6` (can be negative) | -| `fastlzCoef` | `int32` | FastLZ coefficient, scaled by `1e6` (can be negative) | -| `txSizeCoef` | `int32` | Transaction size coefficient, scaled by `1e6` (can be negative) | - -Where: - -- the `l1CostSigned` calculation is an unlimited precision signed integer computation, with the result in Wei and - having `int256` range. - -- the final `l1Cost` computation is an unlimited precision unsigned integer computation, with the result in Wei and - having `uint256` range. - -##### L1-Cost linear regression details - -The `intercept`, `fastlzCoef`, and `txSizeCoef` constants are calculated by linear regression using a dataset -of previous L2 transactions. The dataset is generated by iterating over all transactions in a given time range, and -performing the following actions. For each transaction: - -1. Calculate the RLP-encoded transaction payload. Record the length of this payload as `txSize`. -2. Compress the payload using FastLZ. Record the length of the compressed payload as `fastlzSize`. -3. Compress the payload using a "best estimate" compression, defined as: - -- Create two zlib streams, both using the maximum compression level. -- Bootstrap one of the streams with at least 64kb of transaction data (after compression). -- Write each transaction to both streams (flushing after each write), and record the size increase - of the larger buffer as `bestEstimateSize`. -- Each time the larger buffer grows larger than 128kb, empty the stream and swap the buffers. - -Once this dataset is generated, a linear regression can be calculated using the `bestEstimateSize` as -the dependent variable and `fastlzSize` and `txSize` as the independent variables. - -The following Python code can be used to calculate the linear regression: - -```python -import numpy as np -from sklearn.linear_model import LinearRegression - -# Dataset format is: -# data = [record...] (one or more records, concatenated) -# record = bestEstimateSize ++ fastlzSize ++ txSize -# bestEstimateSize = little-endian uint32 -# fastlzSize = little-endian uint32 -# txSize = little-endian uint32 - -dt = np.dtype([('best', '= 128` scalar-version range and document their `scalar` encoding. - -Invalid and unrecognized scalar event-data should be ignored, -and the last valid configuration should continue to be utilized. - -The scalar values are incorporated into the L2 through the -[Fjord L1 attributes deposit transaction calldata](deposits.md#l1-attributes---fjord). - ### `gasLimit` (`uint64`) The gas limit of the L2 blocks is configured through the system config.