Skip to content

[DS-4601] LLO v31: Merkle batched report signing - #282

Draft
brunotm wants to merge 6 commits into
masterfrom
bm/DS-4601-llo-v31-merkle-signing
Draft

brunotm wants to merge 6 commits into
masterfrom
bm/DS-4601-llo-v31-merkle-signing

Conversation

@brunotm

@brunotm brunotm commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

Adds an opt-in signingScheme: "merkle" for channels on the experimental v31
plugin. Each round, the reports of every Merkle channel in a
signing family go into one bundle. The DON signs the bundle's Merkle root once,
instead of signing every report on its own. The transmitter expands each
attested bundle into one delivery per channel, carrying the report, its proof
and the root signatures. The cost of signing then scales with bundles, not
channels.

DON benchmark: 333,353 B/round/oracle per report vs 11,910 with Merkle.

Move the keyring that signs and verifies LLO reports per report format
into data-streams, next to the report contexts and codecs it depends
on, so a change to how a format is signed ships in one repo.

Hash EVMStreamlined reports with go-ethereum Keccak256, which gives the
same digest without an error path. Add a test that signs with a real
EVM key and recovers the signer from keccak256(digest ‖ report). The
ocr2key test dependency adds its key type modules to go.mod as
indirect requirements.
Add the Merkle tree, bundle and delivery codecs with golden vectors,
and the signingScheme channel field. The empty scheme is left out of
the proto, so channel hashes do not change.

v31 groups the reports of Merkle channels into one bundle per signing
family per round, split by size, and emits it ahead of the staging
marker. Backfill reports follow the scheme of their target channel.

The keyring signs the bundle root once with SignBlob under the family
the bundle carries, and rejects a bundle whose family differs from its
report format. Bundle roots are cached by bundle hash, since libocr
verifies every peer signature over the same bundle.

The transmitter expands each bundle into one delivery per leaf and
queues them in a single commit channel send through
dataengine.TransmitBatch. Add the EVM delivery packer.

v30 does not vote for channels that set a signing scheme.
Chunk transmit queue inserts below the Postgres bind parameter limit.
Exclude EVMStreamlined from the EVM Merkle family current verifiers do
not support EVMStreamlined.
Revert v30 backfill channels whose target is reverted for its signing scheme.
Drop only the failing family when a Merkle bundle fails to encode.
Capture report telemetry only for emitted reports.
Correct the bundle leaf order documented in llo_merkle.proto.
Extract protocol.SigningFamily and v31 MaxReportBytes, and make Transmit
delegate to TransmitBatch.
Add EVMStreamlined as a member of the EVM Merkle family. The
verifier proxy, verifier and fee manager read the feed ID from the
first 32 bytes of the report, so reject signingScheme merkle on a
streamlined channel without one. Leave the feed ID version unchecked,
since NoOpFeeManager ignores the payload.

Restore the streamlined leaves and original golden vectors in the
Merkle tests.
Check the ABI payload ReportCodecEVMMerkle packs, slot by slot, head
offsets, the tag and seqNr in the report context, the v bytes in rawVs,
the report, signature and proof sections, and the total length.
@brunotm
brunotm requested a review from a team as a code owner November 5, 2026 19:02
@brunotm
brunotm marked this pull request as draft November 5, 2026 19:02
@github-actions

github-actions Bot commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

👋 brunotm, thanks for creating this pull request!

To help reviewers, please consider creating future PRs as drafts first. This allows you to self-review and make any final changes before notifying the team.

Once you're ready, you can mark it as "Ready for review" to request feedback. Thanks!

@brunotm
brunotm removed request for a team and Fletch153 November 5, 2026 19:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant