-
Notifications
You must be signed in to change notification settings - Fork 1
fix: emit generic metas as a rain meta document, not a bare cbor map #272
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
Merged
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
d2ef1b8
fix: emit generic metas as a rain meta document, not a bare cbor map
0e05d51
Merge commit '4a688094b279a33f531c9001623f3adb588020ca' into 2026-08-…
thedavidmeister 9d33396
Merge remote-tracking branch 'origin/main' into check272
f13c056
test: send the rust-built calldata to a real metaboard
4cc9380
ci: git-clean regenerates the calldata fixture and diffs it
675248c
ci: satisfy the legal and static lanes for the new files
a451323
refactor: the fixture writer is a writer, not a self-checking test
6cd7ecc
style: cargo fmt the fixture writer
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| // SPDX-License-Identifier: LicenseRef-DCL-1.0 | ||
| // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd | ||
| //! Writes the `emitMeta` calldata the rust encoders produce to | ||
| //! `test/fixtures/emit-calldata.json`, for `test/lib/EmitCalldataFixture.t.sol` | ||
| //! to send to a real metaboard. | ||
| //! | ||
| //! That seam is what neither half tested: rust builds the calldata, solidity | ||
| //! decides whether it is acceptable, and each was only ever checked against its | ||
| //! own idea of the bytes. `generate_emit_meta_calldata` built a bare cbor map | ||
| //! that `LibMeta.checkMetaUnhashedV1` reverts `NotRainMetaV1` on, with both | ||
| //! suites green. | ||
| //! | ||
| //! `script/build.sh` runs this and git-clean diffs the result, so a producer | ||
| //! that changes without its fixture being committed turns the lane red. That is | ||
| //! the same treatment the committed abis get from `CopyArtifacts.sol`. | ||
|
|
||
| use std::{fs, path::PathBuf}; | ||
|
|
||
| use rain_metadata::{ | ||
| ContentEncoding, ContentLanguage, ContentType, KnownMagic, RainMetaDocumentV1Item, | ||
| generate_dotrain_source_emit_tx_data, generate_emit_meta_calldata, | ||
| }; | ||
|
|
||
| /// A meta item with every optional field defaulted, so the fixture pins the | ||
| /// shortest encoding rather than an unusually decorated one. | ||
| fn plain_item(content: &str) -> RainMetaDocumentV1Item { | ||
| RainMetaDocumentV1Item { | ||
| payload: serde_bytes::ByteBuf::from(content.as_bytes().to_vec()), | ||
| magic: KnownMagic::DotrainSourceV1, | ||
| content_type: ContentType::OctetStream, | ||
| content_encoding: ContentEncoding::None, | ||
| content_language: ContentLanguage::None, | ||
| schema: None, | ||
| } | ||
| } | ||
|
|
||
| fn main() { | ||
| let mut cases = serde_json::Map::new(); | ||
|
|
||
| let generic = generate_emit_meta_calldata(plain_item("emit calldata fixture")).unwrap(); | ||
| cases.insert( | ||
| "generic_item".to_string(), | ||
| alloy::hex::encode_prefixed(generic).into(), | ||
| ); | ||
|
|
||
| let dotrain = generate_dotrain_source_emit_tx_data("#main _ _: int-add(1 2);").unwrap(); | ||
| cases.insert("dotrain_source".to_string(), dotrain.calldata.into()); | ||
|
|
||
| let path = | ||
| PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../test/fixtures/emit-calldata.json"); | ||
| fs::create_dir_all(path.parent().unwrap()).unwrap(); | ||
| fs::write( | ||
| &path, | ||
| serde_json::to_string_pretty(&serde_json::Value::Object(cases)).unwrap() + "\n", | ||
| ) | ||
| .unwrap(); | ||
| } |
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| #!/usr/bin/env bash | ||
| # SPDX-License-Identifier: LicenseRef-DCL-1.0 | ||
| # SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd | ||
| # Regenerate derived artifacts that forge cannot produce. | ||
| # | ||
| # The `rainix-copy-artifacts` workflow runs this after its forge steps and then | ||
| # asserts `git diff --exit-code`, so anything written here is held to the same | ||
| # freshness bar as the committed abis: change a producer without committing what | ||
| # it now produces and git-clean goes red. | ||
| # | ||
| # Runs outside any nix devshell, so each command picks its own. | ||
| set -euo pipefail | ||
|
|
||
| # The `emitMeta` calldata the rust encoders produce, consumed by | ||
| # `test/lib/EmitCalldataFixture.t.sol`, which sends it to a real metaboard. The | ||
| # fixture is how the solidity half gets to judge bytes the rust half built. | ||
| nix develop -c cargo run -p rain-metadata --example emit-calldata-fixture |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| { | ||
| "dotrain_source": "0x37480e2a3fd2b7b238e68674f97d936e0e457eae32fe6b647984644c1162c9885502f68600000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000049ff0a89c674ee7874a3005818236d61696e205f205f3a20696e742d61646428312032293b011bffa15ef0fc4370990278186170706c69636174696f6e2f6f637465742d73747265616d0000000000000000000000000000000000000000000000", | ||
| "generic_item": "0x37480e2aa8a816410fb3aa58c6c2440b66b741d975394347626bd243dc08c6444ae9a29f00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000045ff0a89c674ee7874a30055656d69742063616c6c646174612066697874757265011bffa15ef0fc4370990278186170706c69636174696f6e2f6f637465742d73747265616d000000000000000000000000000000000000000000000000000000" | ||
| } | ||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,74 @@ | ||
| // SPDX-License-Identifier: LicenseRef-DCL-1.0 | ||
| // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd | ||
| pragma solidity =0.8.25; | ||
|
|
||
| import {Test, Vm} from "forge-std-1.16.2/src/Test.sol"; | ||
| import {IMetaV1_2} from "src/interface/unstable/IMetaV1_2.sol"; | ||
| import {TestMetaBoard} from "test/concrete/TestMetaBoard.sol"; | ||
|
|
||
| /// @title EmitCalldataFixtureTest | ||
| /// @notice The rust half of this repo builds `emitMeta` calldata and the | ||
| /// solidity half decides whether it is acceptable, and until now nothing tested | ||
| /// that seam: each half was checked against its own idea of the bytes. That is | ||
| /// how `generate_emit_meta_calldata` came to build a bare cbor map, which | ||
| /// `LibMeta.checkMetaUnhashedV1` reverts `NotRainMetaV1` on, while both test | ||
| /// suites stayed green. | ||
| /// | ||
| /// `crates/cli/tests/emit_calldata_fixture.rs` writes the calldata rust | ||
| /// actually produces to `test/fixtures/emit-calldata.json` and fails if the | ||
| /// committed copy is stale. This sends that calldata to a real metaboard, so | ||
| /// what accepts or rejects it is the contract rather than an assertion | ||
| /// restating what the encoder did. | ||
| contract EmitCalldataFixtureTest is Test { | ||
| TestMetaBoard internal metaBoard; | ||
|
|
||
| function setUp() external { | ||
| metaBoard = new TestMetaBoard(); | ||
| } | ||
|
|
||
| /// Every entry in the fixture is calldata a metaboard accepts, and emits | ||
| /// verbatim as a single `MetaV1_2`. A case that reverts fails here rather | ||
| /// than in production. | ||
| /// @param key The fixture key naming the rust producer under test. | ||
| function _checkFixtureCase(string memory key) internal { | ||
| string memory json = vm.readFile("test/fixtures/emit-calldata.json"); | ||
| bytes memory callData = vm.parseJsonBytes(json, string.concat(".", key)); | ||
|
|
||
| vm.recordLogs(); | ||
| (bool success,) = address(metaBoard).call(callData); | ||
| assertTrue(success, string.concat("metaboard rejected calldata for ", key)); | ||
|
|
||
| Vm.Log[] memory logs = vm.getRecordedLogs(); | ||
| assertEq(logs.length, 1, string.concat("log count for ", key)); | ||
| assertEq(logs[0].topics[0], IMetaV1_2.MetaV1_2.selector, string.concat("topic for ", key)); | ||
|
|
||
| // The emitted meta is the calldata's own meta argument, carried | ||
| // verbatim. Decoding the log against the calldata rather than against a | ||
| // literal keeps this test about the seam and not about the encoding. | ||
| (bytes32 subjectArg, bytes memory metaArg) = abi.decode(_args(callData), (bytes32, bytes)); | ||
| (address sender, bytes32 subject, bytes memory meta) = abi.decode(logs[0].data, (address, bytes32, bytes)); | ||
| assertEq(sender, address(this), string.concat("sender for ", key)); | ||
| assertEq(subject, subjectArg, string.concat("subject for ", key)); | ||
| assertEq(meta, metaArg, string.concat("meta for ", key)); | ||
| } | ||
|
|
||
| /// The abi encoded arguments, with the four byte selector dropped. | ||
| /// callData Whole calldata as the fixture carries it. | ||
| /// out The arguments alone, decodable as `(bytes32, bytes)`. | ||
| function _args(bytes memory callData) internal pure returns (bytes memory out) { | ||
| out = new bytes(callData.length - 4); | ||
| for (uint256 i = 0; i < out.length; i++) { | ||
| out[i] = callData[i + 4]; | ||
| } | ||
| } | ||
|
|
||
| /// `generate_emit_meta_calldata`, the generic producer. | ||
| function testGenericItemCalldataIsAcceptable() external { | ||
| _checkFixtureCase("generic_item"); | ||
| } | ||
|
|
||
| /// `generate_dotrain_source_emit_tx_data`, the dotrain producer. | ||
| function testDotrainSourceCalldataIsAcceptable() external { | ||
| _checkFixtureCase("dotrain_source"); | ||
| } | ||
| } |
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.