feat(node): multi-blob derivation support (V2 batch)#937
Open
curryxbo wants to merge 1 commit intofeat/multi_batchfrom
Open
feat(node): multi-blob derivation support (V2 batch)#937curryxbo wants to merge 1 commit intofeat/multi_batchfrom
curryxbo wants to merge 1 commit intofeat/multi_batchfrom
Conversation
Align node-side derivation with feat/multi_batch's V2 batch format so
that multi-blob batches produced by tx-submitter can be decoded and
verified end-to-end.
Changes
- node/types/batch_header.go
- Add BatchHeaderVersion2 (=2) and expectedLengthV2 (=257, reuses V1
wire layout).
- BlobVersionedHash() now errors on V2+ so callers do not silently
treat the aggregated hash as a single blob hash.
- New BlobHashesHash() accessor returns the aggregated blob hash
(keccak(hash[0]||...||hash[N-1])) stored at offset 57 for V2+.
- node/derivation/batch_info.go
- Rewrite ParseBatch: concatenate all blob raw scalar bytes in tx
order first, then perform a single zstd.DecompressBatchBytes.
The prior per-blob decompress-then-append path is incompatible with
tx-submitter's "compress whole batch, then split into blobs"
strategy (only the first blob carries a valid zstd stream header).
- node/derivation/derivation.go
- fetchRollupDataByTxHash: index beacon sidecars by KZG-derived
versioned hash and reassemble the local BlobTxSidecar in the exact
order declared by tx.BlobHashes(). Beacon API ordering is not
guaranteed; any reordering corrupts the concatenated zstd stream.
- Enable per-blob VerifyBlobProof so a bad blob is located before
concatenation rather than misattributed to a decompression failure.
Tests
- node/types/batch_test.go
- TestBatchHeaderV2: V2 257-byte layout + aggregated hash at offset 57.
- TestBlobHashesHashUnavailableForLegacy: V0/V1 reject BlobHashesHash.
- node/derivation/batch_info_test.go (new)
- TestParseBatchSingleBlob: backward-compat single-blob path.
- TestParseBatchMultiBlob: forces compressed payload across 2 blobs
using random incompressible data; verifies concat-then-decompress.
- TestParseBatchMultiBlobConcatDecompressInvariant: direct regression
guarding the low-level invariant ParseBatch now relies on.
Spec reference
- morph-specs spec-002-multi-blob-batch-submission §3.2 step 7, §4.2.5.
Contributor
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Complete the last remaining piece on
feat/multi_batch: node-side derivation support for V2 multi-blob batches. V2 support on the contracts / prover / challenger sides has already landed onfeat/multi_batch; this PR fills in the derivation gap so that multi-blob batches can be decoded end-to-end.Key design points (aligned with
morph-specsspec-002 §3.2 step 7 and §4.2.5):Concat first, decompress once. tx-submitter for V2 compresses the entire
batchBytesas a single zstd stream and then splits it across blobs byMaxBlobBytesSize. Only blob[0] carries a valid zstd frame header; blob[1..N-1] are middle bytes. The previous implementation decompressed each blob independently and appended the results, which fails as soon as more than one blob is used. The new path iterates blobs intx.BlobHashes()order, extracts raw scalar bytes, concatenates into a single buffer, and callszstd.DecompressBatchBytesexactly once.Strict reordering against
tx.BlobHashes(). The Beacon API does not guarantee sidecar order matches the L1 tx's declared blob hashes. Any reordering would corrupt the concatenated zstd stream. We index sidecars by the KZG-derived versioned hash and reassemble the localBlobTxSidecarin exactly the order declared by the tx.Per-blob
VerifyBlobProof. KZG proof verification runs per blob before concatenation. A corrupt blob is located directly instead of being misattributed to a decompression failure downstream.V2 header parsing. V2 reuses V1's 257-byte wire layout, but the semantics of offset 57 change from "single versioned hash" to "aggregated hash
keccak(hash[0]||...||hash[N-1])".BlobVersionedHash()returns an error on V2+ to prevent callers from silently treating the aggregated hash as a single blob hash.BlobHashesHash()accessor returns the aggregated hash; it errors on V0/V1.Changes
node/types/batch_header.goBatchHeaderVersion2 = 2andexpectedLengthV2 = 257.validate()accepts the V2 length.BlobVersionedHash()(V0/V1 only) andBlobHashesHash()(V2+ only), each guarded by a version check.node/derivation/batch_info.goParseBatch()to concatenate all blob raw bytes in tx order first, then perform a singleDecompressBatchBytes.node/derivation/derivation.gofetchRollupDataByTxHash()reorders beacon sidecars bytx.BlobHashes()via a KZG-derived hash index.VerifyBlobProof.Tests
Test Plan
go build ./...passes.commitBatch→ node derivation → state replay.blockCountderivation is correct across the version bump.Related
morph-l2/morph-specs/specs/2026/Q2/spec-002-multi-blob-batch-submissiond78251c4/56bd83ff/9ae6e516), prover multi-blob (2711f073/9894b040/edf823ff), challenger (8c419a78).