-
Notifications
You must be signed in to change notification settings - Fork 72
ZK to MPT #827
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
ZK to MPT #827
Changes from 35 commits
2cdfb07
7c11f8c
98925c5
c34bee9
e39a59a
105c335
a3d76f2
8ae80bd
d5f2d8d
fa2307f
c38ea30
8b2a833
c9f508d
0968304
f4d7b0c
32512d0
b5e977c
5f6ad17
8631ca8
5dea362
772df41
75181a7
6120b0a
89218d0
0a63c6b
a438b20
8abcf7c
d6dd008
abcc805
57cf1e4
0f74ddb
0ec7bda
fd31a72
fae4ad8
ffa5e6d
f11e92a
f34a133
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -31,4 +31,7 @@ contracts/mainnet.json | |
| .env | ||
|
|
||
| # logs | ||
| *.log | ||
| *.log | ||
|
|
||
| # mpt-switch-test (local testing only) | ||
| ops/mpt-switch-test | ||
| +1 −1 | Dockerfile | |
| +5 −8 | core/state_transition.go | |
| +2 −1 | core/token_gas.go | |
| +1 −1 | core/tx_list.go | |
| +1 −1 | core/types/receipt.go | |
| +9 −12 | core/types/token_fee.go | |
| +2 −0 | eth/catalyst/api_types.go | |
| +4 −0 | eth/catalyst/gen_l2blockparams.go | |
| +5 −1 | eth/catalyst/l2_api.go | |
| +3 −3 | eth/catalyst/l2_api_test.go | |
| +2 −1 | ethclient/authclient/engine.go | |
| +0 −1 | internal/ethapi/transaction_args.go | |
| +2 −2 | miner/miner.go | |
| +0 −2 | params/config.go | |
| +2 −2 | params/version.go | |
| +19 −7 | rollup/fees/rate.go | |
| +6 −6 | rollup/fees/token_info.go | |
| +1 −1 | rollup/fees/token_transfer.go |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -56,6 +56,13 @@ type Executor struct { | |||||||||||||||||||||||||||||||||||||||||||||||||||
| rollupABI *abi.ABI | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| batchingCache *BatchingCache | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| // MPT fork handling: force batch points at the 1st and 2nd block after fork. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| // This state machine exists to avoid repeated HeaderByNumber calls after the fork is handled, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| // while keeping results stable if CalculateCapWithProposalBlock is called multiple times at the same height. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| mptForkTime uint64 // cached from geth eth_config.morph.mptForkTime (0 means disabled/unknown) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| mptForkStage uint8 // 0: not handled, 1: forced H1, 2: done (forced H2 or skipped beyond H2) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| mptForkForceHeight uint64 // if equals current height, must return true (stability across multiple calls) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger tmlog.Logger | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| metrics *Metrics | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -71,6 +78,7 @@ func getNextL1MsgIndex(client *types.RetryableClient) (uint64, error) { | |||||||||||||||||||||||||||||||||||||||||||||||||||
| func NewExecutor(newSyncFunc NewSyncerFunc, config *Config, tmPubKey crypto.PubKey) (*Executor, error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger := config.Logger | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger = logger.With("module", "executor") | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| // L2 geth endpoint (required - current geth) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| aClient, err := authclient.DialContext(context.Background(), config.L2.EngineAddr, config.L2.JwtSecret) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil, err | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -80,7 +88,31 @@ func NewExecutor(newSyncFunc NewSyncerFunc, config *Config, tmPubKey crypto.PubK | |||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil, err | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| l2Client := types.NewRetryableClient(aClient, eClient, config.Logger) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| // L2Next endpoint (optional - for upgrade switch) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| var aNextClient *authclient.Client | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| var eNextClient *ethclient.Client | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| if config.L2Next != nil && config.L2Next.EngineAddr != "" && config.L2Next.EthAddr != "" { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| aNextClient, err = authclient.DialContext(context.Background(), config.L2Next.EngineAddr, config.L2Next.JwtSecret) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil, err | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| eNextClient, err = ethclient.Dial(config.L2Next.EthAddr) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil, err | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+91
to
+102
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Close Line 100 returns on error but leaves the auth client open. 🧹 Proposed fixeNextClient, err = ethclient.Dial(config.L2Next.EthAddr)
if err != nil {
+ aNextClient.Close()
return nil, err
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger.Info("L2Next geth configured (upgrade switch enabled)", "engineAddr", config.L2Next.EngineAddr, "ethAddr", config.L2Next.EthAddr) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger.Info("L2Next geth not configured (no upgrade switch)") | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Fetch geth config at startup (with retry to wait for geth) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| gethCfg, err := types.FetchGethConfigWithRetry(config.L2.EthAddr, logger) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil, fmt.Errorf("failed to fetch geth config: %w", err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger.Info("Geth config fetched", "switchTime", gethCfg.SwitchTime, "useZktrie", gethCfg.UseZktrie) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| l2Client := types.NewRetryableClient(aClient, eClient, aNextClient, eNextClient, gethCfg.SwitchTime, logger) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| index, err := getNextL1MsgIndex(l2Client) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil, err | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -123,6 +155,7 @@ func NewExecutor(newSyncFunc NewSyncerFunc, config *Config, tmPubKey crypto.PubK | |||||||||||||||||||||||||||||||||||||||||||||||||||
| batchingCache: NewBatchingCache(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| UpgradeBatchTime: config.UpgradeBatchTime, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| blsKeyCheckForkHeight: config.BlsKeyCheckForkHeight, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| mptForkTime: l2Client.MPTForkTime(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger: logger, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| metrics: PrometheusMetrics("morphnode"), | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -283,16 +316,39 @@ func (e *Executor) DeliverBlock(txs [][]byte, metaData []byte, consensusData l2n | |||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| if wrappedBlock.Number <= height { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| e.logger.Info("ignore it, the block was delivered", "block number", wrappedBlock.Number) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| if e.devSequencer { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil, consensusData.ValidatorSet, nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| e.logger.Info("block already delivered by geth (via P2P sync)", "block_number", wrappedBlock.Number) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Even if block was already delivered (e.g., synced via P2P), we still need to check | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| // if MPT switch should happen, otherwise sentry nodes won't switch to the correct geth. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| e.l2Client.EnsureSwitched(context.Background(), wrappedBlock.Timestamp, wrappedBlock.Number) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| // After switch, re-check height from the new geth client | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| // The block might exist in legacy geth but not in target geth after switch | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| newHeight, err := e.l2Client.BlockNumber(context.Background()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil, nil, err | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| if wrappedBlock.Number > newHeight { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| e.logger.Info("block not in target geth after switch, need to deliver", | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| "block_number", wrappedBlock.Number, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| "old_height", height, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| "new_height", newHeight) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Update height and continue to deliver the block | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| height = newHeight | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| if e.devSequencer { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil, consensusData.ValidatorSet, nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return e.getParamsAndValsAtHeight(int64(wrappedBlock.Number)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
curryxbo marked this conversation as resolved.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| return e.getParamsAndValsAtHeight(int64(wrappedBlock.Number)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| // We only accept the continuous blocks for now. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| // It acts like full sync. Snap sync is not enabled until the Geth enables snapshot with zkTrie | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| if wrappedBlock.Number > height+1 { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| e.logger.Error("!!! CRITICAL: Geth is behind - node BLOCKED !!!", | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| "consensus_block", wrappedBlock.Number, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| "geth_height", height, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| "action", "Switch to MPT-compatible geth IMMEDIATELY") | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil, nil, types.ErrWrongBlockNumber | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -324,7 +380,15 @@ func (e *Executor) DeliverBlock(txs [][]byte, metaData []byte, consensusData l2n | |||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| err = e.l2Client.NewL2Block(context.Background(), l2Block, batchHash) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| e.logger.Error("failed to NewL2Block", "error", err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| e.logger.Error("========================================") | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| e.logger.Error("CRITICAL: Failed to deliver block to geth!") | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| e.logger.Error("========================================") | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| e.logger.Error("failed to NewL2Block", | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| "error", err, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| "block_number", l2Block.Number, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| "block_timestamp", l2Block.Timestamp) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| e.logger.Error("HINT: If this occurs after MPT upgrade, your geth node may not support MPT blocks. " + | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Please ensure you are running an MPT-compatible geth node.") | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil, nil, err | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
morph-l2/go-ethereum v1.10.14 fork changes ABI EVM configuration💡 Result:
Key ABI / tx-format and EVM / chain-config deltas in the morph-l2/go-ethereum line (a Scroll-tech-derived fork originally rooted in the Geth v1.10.x era) are mainly driven by Morph’s hardforks (e.g., Emerald):
ABI / transaction encoding & RPC surface
0x7a): adds a native “pay fees with any token” transaction type, integrated into Morph’s transaction processing (intended to remain compatible with existing wallets/RPC flows). [1]EVM execution changes (Emerald)
CLZopcode (EIP-7939) [2]Chain configuration / fork scheduling knobs
override.emeraldtime→ config fieldOverrideEmeraldTime→ applied via chain overrides during genesis setup. [4]MaxTxPerBlock(100) limit and its initialization in Morph chain configs. [5]config.morph.useZktrieenabling a ZK-friendly trie; note snapshot is disabled with zktrie). [6]If you share the exact Morph tag/commit you mean by “v1.10.14 fork” (e.g.,
morph-v2.0.7,morph-v2.1.0, or a specific SHA), I can map these items to the precise files/struct fields changed in that range.Sources: [1] [2] [3] [4] [5] [6]
🏁 Script executed:
Repository: morph-l2/morph
Length of output: 368
Verify contract artifacts are compatible with Morph fork's EVM and transaction format updates.
The fork introduces significant changes affecting contract tooling:
0x7a) for alternative fee mechanismsEnsure compiled contract ABIs, gas estimates, and codegen tools are regenerated and tested against these changes.
🤖 Prompt for AI Agents