Skip to content

fix: emit generic metas as a rain meta document, not a bare cbor map - #272

Open
thedavidmeister wants to merge 1 commit into
mainfrom
2026-08-25-issue-192
Open

fix: emit generic metas as a rain meta document, not a bare cbor map#272
thedavidmeister wants to merge 1 commit into
mainfrom
2026-08-25-issue-192

Conversation

@thedavidmeister

@thedavidmeister thedavidmeister commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Closes #192.

The issue filed this "flagged, not adjudicated" — the sol half adjudicates it

#192 asks whether the bare-map framing might be deliberate for this API. It is
not, and the deciding fact is in this repo rather than only in the spec.

generate_emit_meta_calldata builds calldata for
IMetaBoardV1_2.emitMeta(subject, meta). That entry point is
LibIMetaBoardV1_2.emitMeta, whose whole body is:

LibMeta.checkMetaUnhashedV1(meta);
emit IMetaV1_2.MetaV1_2(msg.sender, subject, meta);

checkMetaUnhashedV1 reverts NotRainMetaV1 unless the first 8 bytes are
0xff0a89c674ee7874 (src/lib/LibMeta.sol), and IMetaBoardV1_2 states it as
a contract-level MUST: "IMetaBoardV1_2 contracts MUST revert any metadata that
does not start with the Rain metadata magic number."

So this was not a spec-vs-implementation ambiguity with two liveable answers.
Every calldata this function has ever produced reverts on any conforming
metaboard. There is no exemption to document — a "documented exemption" would
have documented a function that cannot be used for its stated purpose.

Two further in-repo oracles agree:

Changes

crates/cli/src/metaboard.rs only:

  • generate_emit_meta_calldata's meta is now
    cbor_encode_seq(&vec![meta], KnownMagic::RainMetaDocumentV1) instead of
    meta.cbor_encode(). A one-item cbor-seq under the magic — which is what
    hash(true) and generate_dotrain_source_emit_tx_data already build, so it
    introduces no new framing.
  • test_generate_emit_meta_calldata_success's meta pin follows.
  • New test_emit_meta_bytes_are_a_rain_meta_document.

What deliberately did NOT change: the subject

The subject stays meta.hash(false) — keccak256 of the BARE cbor item. #192 is
about the meta bytes only, and the bare item hash is the key Store inserts
inner items under (keccak256(meta_map.cbor_encode()) in store_content), so
it is the item's identity in this codebase rather than an arbitrary third
digest. That the subject and the emitted bytes are now over different preimages
looks like an inconsistency at a glance, so the docstring says it is on purpose;
that is the whole of the comment added.

Relation to #247 (2026-08-25-issue-158)

#247 touches the same module and no overlapping line. It changes only
generate_dotrain_source_emit_tx_data's subject (cbor item hash → content
hash) and leaves that path's meta bytes prefixed as they already were. This PR
changes only generate_emit_meta_calldata's meta bytes and leaves its
subject alone. #247's body names the split itself: "the generic
generate_emit_meta_calldata still keys on meta.hash(false), which is a
different question (#192)."

Both branch off the same origin/main (45ca96c). Their metaboard.rs hunks are
disjoint — #247 rewrites the impl body of generate_dotrain_source_emit_tx_data
and the tail of test_generate_dotrain_source_emit_tx_data_success; this one
rewrites the body of generate_emit_meta_calldata and the head of
test_generate_emit_meta_calldata_success — so whichever merges second should
merge clean, and neither changes a value the other asserts.

Behaviour change

generate_emit_meta_calldata is pub and re-exported at the crate root, so
this is wire-visible on a shipped library API: same input, different calldata,
8 bytes longer meta. Called out rather than buried. No in-org consumer exists —
gh search code "generate_emit_meta_calldata org:rainlanguage" returns this
repo's own module and nothing else — and the previous output could not have been
successfully submitted anywhere, so no working caller can regress.

QA

  • Discriminating tests: metaboard::tests::test_emit_meta_bytes_are_a_rain_meta_document
    (new) and metaboard::tests::test_generate_emit_meta_calldata_success (meta
    pin rewritten) — each fails on base, verified by reverting only the impl hunk
    in place (let meta_bytes = meta.cbor_encode()?, tests untouched) and
    re-running: both FAILED, 8 passed / 2 failed. On the fixed tree
    cargo test -p rain-metadata --lib metaboard:: is 10 passed / 0 failed.
  • Mutations applied:
    • crates/cli/src/metaboard.rs let meta_bytes = RainMetaDocumentV1Item::cbor_encode_seq(&vec![meta], crate::KnownMagic::RainMetaDocumentV1)?;
      let meta_bytes = meta.cbor_encode()?; (the original bug is the mutant) →
      killed by test_emit_meta_bytes_are_a_rain_meta_document
      (left: "a3004c7465737420", the bare cbor map header, vs
      right: "ff0a89c674ee7874") and by
      test_generate_emit_meta_calldata_success (emitted meta 8 bytes short).
    • Same line, magic KnownMagic::RainMetaDocumentV1
      KnownMagic::DotrainSourceV1 — prefixed but with the WRONG magic → killed
      by both (left: "ffa15ef0fc437099"), so the new test pins the specific
      magic and not merely "has some prefix".
    • Both mutations reverted; the committed diff is 35 insertions / 2 deletions
      in one file and the working tree is clean against it.
  • Oracle: the literal ff0a89c674ee7874 asserted directly against the emitted
    bytes, not routed through KnownMagic — the same constant
    test/interface/MetaMagicNumberV1.t.sol pins on the sol side, and the value
    quoted in generate_emit_meta_calldata emits meta bytes without the rain-meta-document-v1 magic prefix the metadata-v1 spec requires #192 and in rainprotocol/specs metadata-v1.md. The new test also
    round-trips cbor_decode back to the original item and asserts
    emitted[8..] == meta.cbor_encode(), so the prefix is added and nothing else
    is. The behavioural authority is LibMeta.isRainMetaV1 in this repo, which is
    what actually accepts or rejects the calldata.
  • Category check: generate_emit_meta_calldata emits meta bytes without the rain-meta-document-v1 magic prefix the metadata-v1 spec requires #192 asks (A) the emitted meta bytes do not begin with the
    rain-meta-document-v1 magic the spec requires, and (B) an explicit decision
    between prefixing here too and documenting why this path is exempt. Covered A
    by prefixing. Covered B by deciding, with the reason on the record: exempting
    is not available, because IMetaBoardV1_2.emitMeta — the only consumer of
    this calldata — reverts NotRainMetaV1 on unprefixed meta. generate_emit_meta_calldata emits meta bytes without the rain-meta-document-v1 magic prefix the metadata-v1 spec requires #192's own
    "possibly deliberate" hypotheses are both refuted: there is no wrapping
    caller (no in-org consumer at all), and whether the subgraph checks the prefix
    is moot since the event it indexes is never emitted. The subject question
    generate_emit_meta_calldata emits meta bytes without the rain-meta-document-v1 magic prefix the metadata-v1 spec requires #192 does not ask is left alone and stated above.
  • No sol, subgraph or ABI file is touched, so no CopyArtifacts or manifest
    coupling is in play. cargo fmt --all -- --check and
    cargo clippy --workspace --all-targets -- -D warnings are both clean. Per
    the task brief the wider suite is left to CI (~70 sibling agents on this box).

🤖 Generated with Claude Code

CI

rainix-rs / static / rs-static fails on the rustfmt-conditional hook with
"Failed to find targets" before it reads a single file. It fails the same way on
main itself (45ca96c, 6fe2e2b, 9c65a23 all failure) and on unrelated PRs,
so it is a rainix hook bug and not this change. Every other lane is green.

generate_emit_meta_calldata built emitMeta calldata whose meta was
item.cbor_encode() — the bare cbor map, no 0xff0a89c674ee7874 prefix.
IMetaBoardV1_2.emitMeta reverts NotRainMetaV1 on exactly that, so every
call this function generated was unsubmittable.

Closes #192

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 25, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 18 minutes.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 4fc7f922-7b8d-4cef-a0ae-a76133e73a15

📥 Commits

Reviewing files that changed from the base of the PR and between 45ca96c and d2ef1b8.

📒 Files selected for processing (1)
  • crates/cli/src/metaboard.rs

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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.

generate_emit_meta_calldata emits meta bytes without the rain-meta-document-v1 magic prefix the metadata-v1 spec requires

1 participant