Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Potential Research Area: Separate Dynamic and Static L1 Attributes Values #122

Open
tynes opened this issue Apr 11, 2024 · 9 comments
Open

Comments

@tynes
Copy link
Contributor

tynes commented Apr 11, 2024

As of Ecotone, the L1 Attributes transaction includes the following information:

  • baseFeeScalar
  • blobBaseFeeScalar
  • sequenceNumber
  • l1BlockTimestamp
  • l1BlockNumber  
  • basefee
  • blobBaseFee
  • l1BlockHash
  • batcherHash

Not all of this information changes every L2 block, which is the reasoning behind Diff Based L1 Attributes Transactions. Some fields are guaranteed to change every L2 block like the sequence number, some fields change every time the L1 origin updates (L1 blocknumber, L1 timestamp, etc) and some fields only change based on chain operator input (batcher hash).

For the fields that change automatically based on the L1 origin, we can call those dynamic values. For the values that only change based on chain operator input, we can call those static values.

The custom gas token spec adds a new static value which is the address of the ERC20 that represents the gas paying asset for the L2. A new design pattern is followed where the value is set in the system config and then it triggers a special deposit transaction that is able to set the address directly in the L2's L1Block predeploy. This pattern can be made more generic to work with all static values.

The next time that we need to add a static value to the L1 Attributes transaction, we should:

  • Make a generic pipeline that is very similar to the way that custom gas token deposits its information into L2
  • Remove all static values from the L1 attributes transaction and instead allow them to be configured "just in time" by the generic pipeline

This would allow us to easily allow for the configuration of the batch inbox for example

@0xfuturistic 0xfuturistic self-assigned this May 8, 2024
@alfonso-op alfonso-op changed the title Research Area: Separate Dynamic and Static L1 Attributes Values Holocene: Research Area: Separate Dynamic and Static L1 Attributes Values Aug 1, 2024
@tynes
Copy link
Contributor Author

tynes commented Aug 6, 2024

Much of the design has already been fleshed out for interop. The high level is there is a new setter function on the OptimismPortal for spoofing the depositor address via deposit txs that are able to call the L1Block contract to set important values. This could be "upstreamed" into the mainline contracts as part of holocene to reduce the diff for the interop contracts upgrade.

See the following links:

@roberto-bayardo
Copy link
Contributor

roberto-bayardo commented Aug 16, 2024

Simplification of the diff-based attribute proposal we discussed in discord:

If we remove all static attributes (e.g. the scalars), then as I understand it we're left only with L1 attributes that (for the vast majority of the cases) change with each L1 origin update, with the only exception being sequence number. So assuming we move out all the static attributes, we could, for each L2 block, include only the sequence number, except for L2 blocks with sequencer #0, and they'd have all the L1 origin related attributes following the 0 sequence number. No need for a bitmap - the sequence number itself could indicate whether more attributes need to be parsed.

@tynes added: and we could put the branching logic in the setL1BlockAttributesHolocene function, read u8 from calldata as sequence number, if non zero then return, otherwise read more from the calldata buffer
i think that u8 is safe, can't imagine having that many blocks in an L2 epoch

@tynes
Copy link
Contributor Author

tynes commented Aug 25, 2024

The following mermaid diagram shows the control flow:

graph LR
  subgraph L1
  SystemConfig -- "setConfig(uint8)" --> OptimismPortal
  end
  subgraph L2
  L1Block
  end
  OptimismPortal -- "setConfig(uint8)" --> L1Block
Loading

The argument to setConfig would be an enum, like so:

enum ConfigType {
    SET_GAS_PAYING_TOKEN,
    ADD_DEPENDENCY,  // used in interop
    REMOVE_DEPENDENCY,  // used in interop
    FEE_CONFIG, // replaces SystemConfig.UpdateType.GAS_CONFIG
    BATCHER_HASH, // replaces SystemConfig.UpdateType.BATCHER
    UNSAFE_BLOCK_SIGNER, // replaces SystemConfig.UpdateType.UNSAFE_BLOCK_SIGNER
    GAS_LIMIT // replaces SystemConfig.UpdateType.GAS_LIMIT
}

The SystemConfig would have higher level setters that enable role based access control, an example in the interop contracts can be seen here.

The OptimismPortal would emit a TransactionDeposited event from the identity of an account with no known key, indicating that the deposit is coming from the system. See this example from the interop contracts.

It may be the case that some of the above config types are more difficult to implement, for example the batcher hash influences derivation. We would need to be mindful of code that tracks the SystemConfig representation within the derivation pipeline here. This would replace the need for ConfigUpdate events to be tracked within the derivation pipeline, making the fault proof program much cheaper, see #330

@blockchaindevsh
Copy link

blockchaindevsh commented Aug 26, 2024

This PR serves as a first step for "Separate Dynamic and Static L1 Attributes Values", it migrates existing SystemConfig updates to follow the new pattern.

@BlocksOnAChain
Copy link
Contributor

Relevant pr for tracking work: ethereum-optimism/optimism#11600

@BlocksOnAChain
Copy link
Contributor

We are going to punt this issue and remove it from the Holocene scope, since we plan to focus our on #358 changes only.

@BlocksOnAChain BlocksOnAChain changed the title Holocene: Research Area: Separate Dynamic and Static L1 Attributes Values Potential Research Area: Separate Dynamic and Static L1 Attributes Values Sep 3, 2024
@tynes
Copy link
Contributor Author

tynes commented Sep 3, 2024

The specific reason why this is being descoped is due to the way that it impacts proofs. With #122 (comment) as context, the L1 attributes data is in history (transaction calldata) rather than storage. This means that during derivation, L2 history is able to be accessed arbitrarily. State is a bit trickier to access arbitrarily without archival state access. This proposal involved moving the L1 attributes data to storage by putting it into L2 state and deduplicating the data from being posted over and over again in each L1 attributes transaction.

This can be considered an optimization in the future. Perhaps the model that we want is in each epoch (where sequencer number is 0) we emit an event that includes the most recent L1 attributes data and then store the rest into storage. This gives a "snapshot" of the data over time so that only a small amount of reexecution is required to reproduce the state at a specific L2 blocknumber.

Achieving this will help to remove the need to iterate through all L1 logs searching for UpdateType events, making the derivation pipeline cheaper to execute.

We will still be following the architecture in #122 (comment) but not including any UpdateType enum values

@blockchaindevsh
Copy link

blockchaindevsh commented Sep 5, 2024

This can be considered an optimization in the future. Perhaps the model that we want is in each epoch (where sequencer number is 0) we emit an event that includes the most recent L1 attributes data and then store the rest into storage. This gives a "snapshot" of the data over time so that only a small amount of reexecution is required to reproduce the state at a specific L2 blocknumber.

I'm a bit confused by the purpose of "snapshot".

There're 3 typical cases to access SystemConfig:

  1. in L1Traversal.AdvanceL1Block, where this component needs to know the SystemConfig for a corresponding L1 block. This component should be able to compute SystemConfig soly from L1 events.
  2. in L2Client.SystemConfigByL2Hash, where this component needs to know the SystemConfig for a corresponding L2 block, mostly when reorganization.
    1. I think the purpose of "snapshot" is to make it possible to compute the the SystemConfig for a corresponding L2 block by calculate(snapshot, subsequent_system_config_updates_by_parsing_L2_tx) instead of from L2 history state, is it right? But it seems unnecessary since if you needs to reorg to a history L2 block, you must already have that L2 history state anyway..
  3. for DAPPs, where the user should query the L1Block contract to know the latest SystemConfig in L2. The SystemConfig maintained by L1Block contract is a result of executing deposit transactions generated by L1.

@tynes
Copy link
Contributor Author

tynes commented Sep 17, 2024

Including historical context for the diff based L1 attributes tx as one attempt to deduplicate calldata from the L1 attributes tx: #375

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants