From abc4669c4418fd94bb79a4217b149a375f7f6166 Mon Sep 17 00:00:00 2001 From: topocount <17910833+topocount@users.noreply.github.com> Date: Wed, 17 Jun 2026 14:21:19 -0500 Subject: [PATCH 1/2] vectors: add L0 conformance corpus + spec reference MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a versioned, checked-in set of golden conformance vectors for the message cryptographic layer (canonical data_bytes serialization, BLAKE3-160 hash, Ed25519 signature, signer), generated by the reference implementation (farcasterxyz/snapchain) and mirrored here as the cross-client source of truth for FIP validator-onboarding gate L0. - vectors/v1/: manifest.json (hex of every field + semantic input) plus messages/.pb (authoritative wire bytes) and messages/.pb.txt (reviewable wire disassembly). 10 message types. - vectors/README.md: corpus format + the language-agnostic verification algorithm (verify hash/signature against the carried data_bytes; do not re-encode, since protobuf serialization is not canonical across impls). - SPECIFICATION.md §2: a "Conformance Vectors" subsection pointing at them. Post-state merkle roots are intentionally omitted: §4.2's trie spec is stale relative to the reference implementation's sharded trie. Reconciling that (and then adding state-root vectors) is tracked separately. --- docs/SPECIFICATION.md | 4 + vectors/README.md | 50 ++++ vectors/v1/manifest.json | 226 ++++++++++++++++++ vectors/v1/messages/cast_add_basic.pb | Bin 0 -> 196 bytes vectors/v1/messages/cast_add_basic.pb.txt | 18 ++ vectors/v1/messages/cast_remove.pb | Bin 0 -> 202 bytes vectors/v1/messages/cast_remove.pb.txt | 18 ++ vectors/v1/messages/key_add_ed25519.pb | Bin 0 -> 976 bytes vectors/v1/messages/key_add_ed25519.pb.txt | 25 ++ vectors/v1/messages/key_remove_custody.pb | Bin 0 -> 380 bytes vectors/v1/messages/key_remove_custody.pb.txt | 22 ++ vectors/v1/messages/link_add_follow.pb | Bin 0 -> 180 bytes vectors/v1/messages/link_add_follow.pb.txt | 19 ++ vectors/v1/messages/link_remove_follow.pb | Bin 0 -> 180 bytes vectors/v1/messages/link_remove_follow.pb.txt | 19 ++ vectors/v1/messages/reaction_add_like.pb | Bin 0 -> 216 bytes vectors/v1/messages/reaction_add_like.pb.txt | 22 ++ vectors/v1/messages/reaction_remove_like.pb | Bin 0 -> 216 bytes .../v1/messages/reaction_remove_like.pb.txt | 22 ++ vectors/v1/messages/user_data_add_display.pb | Bin 0 -> 184 bytes .../v1/messages/user_data_add_display.pb.txt | 19 ++ vectors/v1/messages/verification_add_eth.pb | Bin 0 -> 406 bytes .../v1/messages/verification_add_eth.pb.txt | 20 ++ 23 files changed, 484 insertions(+) create mode 100644 vectors/README.md create mode 100644 vectors/v1/manifest.json create mode 100644 vectors/v1/messages/cast_add_basic.pb create mode 100644 vectors/v1/messages/cast_add_basic.pb.txt create mode 100644 vectors/v1/messages/cast_remove.pb create mode 100644 vectors/v1/messages/cast_remove.pb.txt create mode 100644 vectors/v1/messages/key_add_ed25519.pb create mode 100644 vectors/v1/messages/key_add_ed25519.pb.txt create mode 100644 vectors/v1/messages/key_remove_custody.pb create mode 100644 vectors/v1/messages/key_remove_custody.pb.txt create mode 100644 vectors/v1/messages/link_add_follow.pb create mode 100644 vectors/v1/messages/link_add_follow.pb.txt create mode 100644 vectors/v1/messages/link_remove_follow.pb create mode 100644 vectors/v1/messages/link_remove_follow.pb.txt create mode 100644 vectors/v1/messages/reaction_add_like.pb create mode 100644 vectors/v1/messages/reaction_add_like.pb.txt create mode 100644 vectors/v1/messages/reaction_remove_like.pb create mode 100644 vectors/v1/messages/reaction_remove_like.pb.txt create mode 100644 vectors/v1/messages/user_data_add_display.pb create mode 100644 vectors/v1/messages/user_data_add_display.pb.txt create mode 100644 vectors/v1/messages/verification_add_eth.pb create mode 100644 vectors/v1/messages/verification_add_eth.pb.txt diff --git a/docs/SPECIFICATION.md b/docs/SPECIFICATION.md index ce74f3e..3374429 100644 --- a/docs/SPECIFICATION.md +++ b/docs/SPECIFICATION.md @@ -115,6 +115,10 @@ Messages are totally ordered by timestamp and hash. Assume two messages $m$ and A pairwise comparison of two distinct hashes $x$ and $y$ is performed by comparing the ASCII values of the characters in $x$ and $y$ in order. The hash which has a higher ASCII character value for a distinct pair has the highest order. +### Conformance Vectors + +A versioned set of golden conformance vectors for the message cryptographic layer (canonical `data_bytes` serialization, BLAKE3-160 `hash`, Ed25519 `signature`, and `signer`) is checked in under [`/vectors`](../vectors). Each vector carries its `data_bytes` so that a client can verify the `hash` and `signature` against the exact serialization they were produced over, without needing to reproduce another implementation's encoding (see the note on serialization inconsistency above). An alternative client can run these vectors in its own CI to prove encoding/hash/signature parity with the reference implementation. + ## 2.1 Message Data A MessageData contains the payload of the Message, which is hashed and signed to produce the message. diff --git a/vectors/README.md b/vectors/README.md new file mode 100644 index 0000000..4eec5c8 --- /dev/null +++ b/vectors/README.md @@ -0,0 +1,50 @@ +# Conformance vectors + +Versioned, checked-in golden vectors that pin the byte-exact output of a Farcaster message's +cryptographic layer: the canonical `MessageData` serialization, the BLAKE3-160 hash, the Ed25519 +signature, and the signer. They let an alternative client prove, in its own CI, that it produces and +verifies messages identically to the reference implementation (FIP validator-onboarding, gate L0). + +These vectors are generated by the reference implementation +([`farcasterxyz/snapchain`](https://github.com/farcasterxyz/snapchain), `tests/conformance_test.rs`) +and mirrored here as the canonical, cross-client source of truth. + +## Scope + +This corpus covers the **crypto layer** only — encoding, hashing, and signing — which rests on protobuf + +BLAKE3 + Ed25519 and is reproducible in any language. Post-state merkle roots (the trie state +transition) are not yet included: the trie layout in [`SPECIFICATION.md` §4.2](../docs/SPECIFICATION.md) +is currently stale relative to the reference implementation's sharded trie, and is tracked for +reconciliation before state-root vectors are added here. + +## Layout + +``` +v/ + manifest.json # vector metadata + expected values (hex) + messages/.pb # the encoded protobuf Message for each vector (authoritative bytes) + messages/.pb.txt # human-reviewable wire disassembly of the .pb (review aid) +``` + +Each manifest vector carries: the semantic `input`, the fixed `signer_private_key` and `timestamp`, +and an `expected` block with hex `data_bytes`, `hash`, `signature`, `signer`, and `message_bytes`. + +## Verification algorithm + +Protobuf serialization is not canonical across implementations (e.g. encoders differ on empty +`repeated` fields), so a client cannot reproduce the encoding from the semantic fields alone. Per +[`SPECIFICATION.md` §2](../docs/SPECIFICATION.md) (Hashing), the hash and signature are computed over +a carried serialization in the `data_bytes` field. Every vector message carries `data_bytes`. A +conforming client: + +1. Decodes the wire `Message` from `messages/.pb`. +2. Reads `message.data_bytes` and checks it equals `expected.data_bytes`. +3. Computes `hash = BLAKE3(data_bytes)[0..20]`; checks it equals `expected.hash` and `message.hash`. +4. Verifies the Ed25519 `signature` over `hash` with `signer`; checks bytes equal `expected.*`. +5. Decodes `data_bytes` into a `MessageData` and checks the semantic fields match. + +Clients must **not** assert that re-encoding `MessageData` reproduces `data_bytes` — that is not +portable across encoders and is exactly why `data_bytes` exists. + +A reference verifier (TypeScript / `@farcaster/core`) lives in the snapchain repo at +`tests/client_parity_tests/conformance.test.ts`. diff --git a/vectors/v1/manifest.json b/vectors/v1/manifest.json new file mode 100644 index 0000000..ef273c0 --- /dev/null +++ b/vectors/v1/manifest.json @@ -0,0 +1,226 @@ +{ + "corpus_version": 1, + "generated_by": "farcasterxyz/snapchain conformance_test.rs", + "note": "Crypto-layer (encoding/hash/signature) conformance vectors. Post-state merkle roots are omitted; snapchain\u2019s trie diverges from SPECIFICATION.md \u00a74.2 (stale) and is tracked for reconciliation.", + "vectors": [ + { + "id": "cast_add_basic", + "description": "CastAdd with simple text body.", + "message_type": "CastAdd", + "fid": 1234, + "timestamp": 94608000, + "signer_private_key": "1000000000000000000000000000000000000000000000000000000000000000", + "input": { + "text": "Hello, Farcaster!", + "type": "CAST" + }, + "message_file": "messages/cast_add_basic.pb", + "expected": { + "data_bytes": "080110d2091880b58e2d20012a13221148656c6c6f2c2046617263617374657221", + "hash": "27f49c6928369d64495f4c4dd142c2e7389ebf1e", + "signature": "4f67a836aa72f3c5a2658126479748ffb21d9cb862bccacd2a731990d1650ee6334d993a4563190bc96242f37da24c2de79c6c425d35a7ec3995454e90cb3f0f", + "signer": "69104ef20c6676aacc9e8c291800d1b7e911e20f85b4066156ea118ace44b8d7", + "message_bytes": "0a21080110d2091880b58e2d20012a13221148656c6c6f2c2046617263617374657221121427f49c6928369d64495f4c4dd142c2e7389ebf1e180122404f67a836aa72f3c5a2658126479748ffb21d9cb862bccacd2a731990d1650ee6334d993a4563190bc96242f37da24c2de79c6c425d35a7ec3995454e90cb3f0f2801322069104ef20c6676aacc9e8c291800d1b7e911e20f85b4066156ea118ace44b8d73a21080110d2091880b58e2d20012a13221148656c6c6f2c2046617263617374657221" + } + }, + { + "id": "cast_remove", + "description": "CastRemove targeting a fixed cast hash.", + "message_type": "CastRemove", + "fid": 1234, + "timestamp": 94608000, + "signer_private_key": "1000000000000000000000000000000000000000000000000000000000000000", + "input": { + "target_hash": "0101010101010101010101010101010101010101" + }, + "message_file": "messages/cast_remove.pb", + "expected": { + "data_bytes": "080210d2091880b58e2d200132160a140101010101010101010101010101010101010101", + "hash": "b7d1cd976fb46bf5a6fdbdca32717c8404277e2d", + "signature": "962a31a2614c59c56290c9e6f7ea85bef3248ef7e51c91cdb9bb6d43ef4bfc7f7287cfdadf4a53e836969e324bce4283dbe2a4b5cde33ac61359bad9f0f7a20b", + "signer": "69104ef20c6676aacc9e8c291800d1b7e911e20f85b4066156ea118ace44b8d7", + "message_bytes": "0a24080210d2091880b58e2d200132160a1401010101010101010101010101010101010101011214b7d1cd976fb46bf5a6fdbdca32717c8404277e2d18012240962a31a2614c59c56290c9e6f7ea85bef3248ef7e51c91cdb9bb6d43ef4bfc7f7287cfdadf4a53e836969e324bce4283dbe2a4b5cde33ac61359bad9f0f7a20b2801322069104ef20c6676aacc9e8c291800d1b7e911e20f85b4066156ea118ace44b8d73a24080210d2091880b58e2d200132160a140101010101010101010101010101010101010101" + } + }, + { + "id": "reaction_add_like", + "description": "ReactionAdd (LIKE) targeting a fixed cast id.", + "message_type": "ReactionAdd", + "fid": 1234, + "timestamp": 94608000, + "signer_private_key": "1000000000000000000000000000000000000000000000000000000000000000", + "input": { + "reaction_type": "LIKE", + "target_cast": { + "fid": 321, + "hash": "0202020202020202020202020202020202020202" + } + }, + "message_file": "messages/reaction_add_like.pb", + "expected": { + "data_bytes": "080310d2091880b58e2d20013a1d0801121908c10212140202020202020202020202020202020202020202", + "hash": "bbe457a26f1099b0d75d9965bcac691bbb4ce49a", + "signature": "fd1437f0e113e62aec51505f430961616ff07febb4a17da203b103a5dc4d7979ae9cecc983ceba819537c7ee6a1e218757098ece0860a01d738cea4bebde0907", + "signer": "69104ef20c6676aacc9e8c291800d1b7e911e20f85b4066156ea118ace44b8d7", + "message_bytes": "0a2b080310d2091880b58e2d20013a1d0801121908c102121402020202020202020202020202020202020202021214bbe457a26f1099b0d75d9965bcac691bbb4ce49a18012240fd1437f0e113e62aec51505f430961616ff07febb4a17da203b103a5dc4d7979ae9cecc983ceba819537c7ee6a1e218757098ece0860a01d738cea4bebde09072801322069104ef20c6676aacc9e8c291800d1b7e911e20f85b4066156ea118ace44b8d73a2b080310d2091880b58e2d20013a1d0801121908c10212140202020202020202020202020202020202020202" + } + }, + { + "id": "reaction_remove_like", + "description": "ReactionRemove (LIKE) targeting a fixed cast id.", + "message_type": "ReactionRemove", + "fid": 1234, + "timestamp": 94608000, + "signer_private_key": "1000000000000000000000000000000000000000000000000000000000000000", + "input": { + "reaction_type": "LIKE", + "target_cast": { + "fid": 321, + "hash": "0202020202020202020202020202020202020202" + } + }, + "message_file": "messages/reaction_remove_like.pb", + "expected": { + "data_bytes": "080410d2091880b58e2d20013a1d0801121908c10212140202020202020202020202020202020202020202", + "hash": "8126e4974487b4ca4fff521c5caa2515b292f203", + "signature": "e3d834c6cb17d477358a40e2ec111205a189d2f36d4dcc7a46f6d1a5dee88e0f668a6327154c8557b303178a80a9c1c70e26c94c617f0681d293d6d72c064f06", + "signer": "69104ef20c6676aacc9e8c291800d1b7e911e20f85b4066156ea118ace44b8d7", + "message_bytes": "0a2b080410d2091880b58e2d20013a1d0801121908c1021214020202020202020202020202020202020202020212148126e4974487b4ca4fff521c5caa2515b292f20318012240e3d834c6cb17d477358a40e2ec111205a189d2f36d4dcc7a46f6d1a5dee88e0f668a6327154c8557b303178a80a9c1c70e26c94c617f0681d293d6d72c064f062801322069104ef20c6676aacc9e8c291800d1b7e911e20f85b4066156ea118ace44b8d73a2b080410d2091880b58e2d20013a1d0801121908c10212140202020202020202020202020202020202020202" + } + }, + { + "id": "link_add_follow", + "description": "LinkAdd (follow) targeting a fixed fid.", + "message_type": "LinkAdd", + "fid": 1234, + "timestamp": 94608000, + "signer_private_key": "1000000000000000000000000000000000000000000000000000000000000000", + "input": { + "target_fid": 456, + "type": "follow" + }, + "message_file": "messages/link_add_follow.pb", + "expected": { + "data_bytes": "080510d2091880b58e2d2001720b0a06666f6c6c6f7718c803", + "hash": "17e218e50051a6fc3f2e37431f1d981624e42b0a", + "signature": "da44df7bc0723fa5365539871d0f73bc656362ba0c091be5d66031a7bbc868b83dd229bf2e490b709c3888fbc3eb28e1c258726b8c3b577937bce3616d576103", + "signer": "69104ef20c6676aacc9e8c291800d1b7e911e20f85b4066156ea118ace44b8d7", + "message_bytes": "0a19080510d2091880b58e2d2001720b0a06666f6c6c6f7718c803121417e218e50051a6fc3f2e37431f1d981624e42b0a18012240da44df7bc0723fa5365539871d0f73bc656362ba0c091be5d66031a7bbc868b83dd229bf2e490b709c3888fbc3eb28e1c258726b8c3b577937bce3616d5761032801322069104ef20c6676aacc9e8c291800d1b7e911e20f85b4066156ea118ace44b8d73a19080510d2091880b58e2d2001720b0a06666f6c6c6f7718c803" + } + }, + { + "id": "link_remove_follow", + "description": "LinkRemove (follow) targeting a fixed fid.", + "message_type": "LinkRemove", + "fid": 1234, + "timestamp": 94608000, + "signer_private_key": "1000000000000000000000000000000000000000000000000000000000000000", + "input": { + "target_fid": 456, + "type": "follow" + }, + "message_file": "messages/link_remove_follow.pb", + "expected": { + "data_bytes": "080610d2091880b58e2d2001720b0a06666f6c6c6f7718c803", + "hash": "1fe5ec1ebf33898d74c9cc106403784d14c48862", + "signature": "f8aa33e288b6a9e30d5f813e8aad2ace7e98de9f512325e8a79f0d58b95a4d89cbc6ec8cdb99d231fb1a2f3934846071bca2eb44080c1a10a3aa6b8a377b8405", + "signer": "69104ef20c6676aacc9e8c291800d1b7e911e20f85b4066156ea118ace44b8d7", + "message_bytes": "0a19080610d2091880b58e2d2001720b0a06666f6c6c6f7718c80312141fe5ec1ebf33898d74c9cc106403784d14c4886218012240f8aa33e288b6a9e30d5f813e8aad2ace7e98de9f512325e8a79f0d58b95a4d89cbc6ec8cdb99d231fb1a2f3934846071bca2eb44080c1a10a3aa6b8a377b84052801322069104ef20c6676aacc9e8c291800d1b7e911e20f85b4066156ea118ace44b8d73a19080610d2091880b58e2d2001720b0a06666f6c6c6f7718c803" + } + }, + { + "id": "user_data_add_display", + "description": "UserDataAdd setting the DISPLAY name.", + "message_type": "UserDataAdd", + "fid": 1234, + "timestamp": 94608000, + "signer_private_key": "1000000000000000000000000000000000000000000000000000000000000000", + "input": { + "type": "DISPLAY", + "value": "Test User" + }, + "message_file": "messages/user_data_add_display.pb", + "expected": { + "data_bytes": "080b10d2091880b58e2d2001620d08021209546573742055736572", + "hash": "60ee272dd458e0cf081bc3db81a16b26cd56b048", + "signature": "32787cd875d76c739bdf5e1e4be40fd7552a3dcf5b2cfcb683512cc4469cb831bc3fc88d9a33ce784058455eedbb1d5b01c024cdc598328c9cd656e139c86802", + "signer": "69104ef20c6676aacc9e8c291800d1b7e911e20f85b4066156ea118ace44b8d7", + "message_bytes": "0a1b080b10d2091880b58e2d2001620d08021209546573742055736572121460ee272dd458e0cf081bc3db81a16b26cd56b0481801224032787cd875d76c739bdf5e1e4be40fd7552a3dcf5b2cfcb683512cc4469cb831bc3fc88d9a33ce784058455eedbb1d5b01c024cdc598328c9cd656e139c868022801322069104ef20c6676aacc9e8c291800d1b7e911e20f85b4066156ea118ace44b8d73a1b080b10d2091880b58e2d2001620d08021209546573742055736572" + } + }, + { + "id": "verification_add_eth", + "description": "VerificationAddEthAddress with fixed (non-validating) claim fields. Crypto-layer only: a real claim signature is required to merge.", + "message_type": "VerificationAddEthAddress", + "fid": 1234, + "timestamp": 94608000, + "signer_private_key": "1000000000000000000000000000000000000000000000000000000000000000", + "input": { + "address": "0303030303030303030303030303030303030303", + "block_hash": "0404040404040404040404040404040404040404040404040404040404040404", + "chain_id": 0, + "protocol": 0, + "verification_type": 0 + }, + "message_file": "messages/verification_add_eth.pb", + "expected": { + "data_bytes": "080710d2091880b58e2d20014a7b0a140303030303030303030303030303030303030303124105050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505051a200404040404040404040404040404040404040404040404040404040404040404", + "hash": "d0d99255fd8eff839e793a515e5917b003033e31", + "signature": "76a515539e0dc74ee8ce87aadf0a52120ef879bf4fb0f0a23b37d2e08a5ae41dffadefec70ccde335fab0a196add6f18972b28e46ece35995365426a0904d706", + "signer": "69104ef20c6676aacc9e8c291800d1b7e911e20f85b4066156ea118ace44b8d7", + "message_bytes": "0a8901080710d2091880b58e2d20014a7b0a140303030303030303030303030303030303030303124105050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505051a2004040404040404040404040404040404040404040404040404040404040404041214d0d99255fd8eff839e793a515e5917b003033e311801224076a515539e0dc74ee8ce87aadf0a52120ef879bf4fb0f0a23b37d2e08a5ae41dffadefec70ccde335fab0a196add6f18972b28e46ece35995365426a0904d7062801322069104ef20c6676aacc9e8c291800d1b7e911e20f85b4066156ea118ace44b8d73a8901080710d2091880b58e2d20014a7b0a140303030303030303030303030303030303030303124105050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505051a200404040404040404040404040404040404040404040404040404040404040404" + } + }, + { + "id": "key_add_ed25519", + "description": "KeyAdd (off-chain signer) with deterministic EIP-712 custody + metadata signatures. Crypto-layer only: custody registration is required to merge.", + "message_type": "KeyAdd", + "fid": 1234, + "timestamp": 94608000, + "signer_private_key": "1000000000000000000000000000000000000000000000000000000000000000", + "input": { + "app_custody_private_key": "2222222222222222222222222222222222222222222222222222222222222222", + "deadline": 99999999, + "fid_custody_private_key": "1111111111111111111111111111111111111111111111111111111111111111", + "key_type": 1, + "nonce": 1, + "request_fid": 1234, + "scopes": [ + "CAST_ADD" + ], + "ttl": 0 + }, + "message_file": "messages/key_add_ed25519.pb", + "expected": { + "data_bytes": "081010d2091880b58e2d20019a0196030a2069104ef20c6676aacc9e8c291800d1b7e911e20f85b4066156ea118ace44b8d710011a411c86bd397e6e6b77fa92a419550c2a868f8665ed61af7e122f98437b536b8b6063bbe8e7752667e5d4303cd940894189d26a2208911d426bc4c0fe289019ef381c20ffc1d72f280132a002000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004d20000000000000000000000001563915e194d8cfba1943570603f7606a311550800000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000005f5e0ff0000000000000000000000000000000000000000000000000000000000000041df5cadcd4d7f585ddade01de28371dc96bfcd1c1a163c8cb82b429ed4700797963d611356be12d972dc5379ec4d7f297ab498585c832dd6ef9651921992c1b731c0000000000000000000000000000000000000000000000000000000000000038014a0101", + "hash": "424a282bffbf632f16c9dab34fba7df640d8b6a5", + "signature": "3a1033a20947d480217b206219d4d6059d03196cae67adaf937666a5c08e98faa4ebb00ac83abc4042a3855a428861336475f47690d14f0edaf4c9bd5488400f", + "signer": "69104ef20c6676aacc9e8c291800d1b7e911e20f85b4066156ea118ace44b8d7", + "message_bytes": "0aa603081010d2091880b58e2d20019a0196030a2069104ef20c6676aacc9e8c291800d1b7e911e20f85b4066156ea118ace44b8d710011a411c86bd397e6e6b77fa92a419550c2a868f8665ed61af7e122f98437b536b8b6063bbe8e7752667e5d4303cd940894189d26a2208911d426bc4c0fe289019ef381c20ffc1d72f280132a002000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004d20000000000000000000000001563915e194d8cfba1943570603f7606a311550800000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000005f5e0ff0000000000000000000000000000000000000000000000000000000000000041df5cadcd4d7f585ddade01de28371dc96bfcd1c1a163c8cb82b429ed4700797963d611356be12d972dc5379ec4d7f297ab498585c832dd6ef9651921992c1b731c0000000000000000000000000000000000000000000000000000000000000038014a01011214424a282bffbf632f16c9dab34fba7df640d8b6a5180122403a1033a20947d480217b206219d4d6059d03196cae67adaf937666a5c08e98faa4ebb00ac83abc4042a3855a428861336475f47690d14f0edaf4c9bd5488400f2801322069104ef20c6676aacc9e8c291800d1b7e911e20f85b4066156ea118ace44b8d73aa603081010d2091880b58e2d20019a0196030a2069104ef20c6676aacc9e8c291800d1b7e911e20f85b4066156ea118ace44b8d710011a411c86bd397e6e6b77fa92a419550c2a868f8665ed61af7e122f98437b536b8b6063bbe8e7752667e5d4303cd940894189d26a2208911d426bc4c0fe289019ef381c20ffc1d72f280132a002000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004d20000000000000000000000001563915e194d8cfba1943570603f7606a311550800000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000005f5e0ff0000000000000000000000000000000000000000000000000000000000000041df5cadcd4d7f585ddade01de28371dc96bfcd1c1a163c8cb82b429ed4700797963d611356be12d972dc5379ec4d7f297ab498585c832dd6ef9651921992c1b731c0000000000000000000000000000000000000000000000000000000000000038014a0101" + } + }, + { + "id": "key_remove_custody", + "description": "KeyRemove (custody revocation) with a deterministic EIP-712 signature. Crypto-layer only: custody registration is required to merge.", + "message_type": "KeyRemove", + "fid": 1234, + "timestamp": 94608000, + "signer_private_key": "1000000000000000000000000000000000000000000000000000000000000000", + "input": { + "deadline": 99999999, + "fid_custody_private_key": "1111111111111111111111111111111111111111111111111111111111111111", + "nonce": 2, + "signature_type": 1, + "target_key": "0606060606060606060606060606060606060606060606060606060606060606" + }, + "message_file": "messages/key_remove_custody.pb", + "expected": { + "data_bytes": "081110d2091880b58e2d2001a2016e0a20060606060606060606060606060606060606060606060606060606060606060612419a7ae0a0284747b8fab028499bfb9195b8f60dd317160c754dbee389356264dc4e225cf4c89b88a05ba0895c91b18da433c7acb24607444ba562cf86ada39e3a1c180120ffc1d72f2802", + "hash": "7f9231b62f033121a5c3fff3d7e2a560c9b27cba", + "signature": "6253fa5af0b1543e4524b806b61d037a46a4f55e4fb8487306027c2a8462fd1ce951ddc6ff0ad76ddc51ff3bd06c81b8e3372013bdb45e3e139d1c3173c99208", + "signer": "69104ef20c6676aacc9e8c291800d1b7e911e20f85b4066156ea118ace44b8d7", + "message_bytes": "0a7d081110d2091880b58e2d2001a2016e0a20060606060606060606060606060606060606060606060606060606060606060612419a7ae0a0284747b8fab028499bfb9195b8f60dd317160c754dbee389356264dc4e225cf4c89b88a05ba0895c91b18da433c7acb24607444ba562cf86ada39e3a1c180120ffc1d72f280212147f9231b62f033121a5c3fff3d7e2a560c9b27cba180122406253fa5af0b1543e4524b806b61d037a46a4f55e4fb8487306027c2a8462fd1ce951ddc6ff0ad76ddc51ff3bd06c81b8e3372013bdb45e3e139d1c3173c992082801322069104ef20c6676aacc9e8c291800d1b7e911e20f85b4066156ea118ace44b8d73a7d081110d2091880b58e2d2001a2016e0a20060606060606060606060606060606060606060606060606060606060606060612419a7ae0a0284747b8fab028499bfb9195b8f60dd317160c754dbee389356264dc4e225cf4c89b88a05ba0895c91b18da433c7acb24607444ba562cf86ada39e3a1c180120ffc1d72f2802" + } + } + ] +} diff --git a/vectors/v1/messages/cast_add_basic.pb b/vectors/v1/messages/cast_add_basic.pb new file mode 100644 index 0000000000000000000000000000000000000000..176d9c8d57d188bfccb8bb74f35080b98e5d46fb GIT binary patch literal 196 zcmd;5OHR0$%Ja-MKs0`Mvj_`l9ypx9)odzc8CN&&d0nQ}gXd zOSYbUY;{aHa@Wld-xqOfFd8Xj3iy5ENh@1*W?qk`1jEJcF9jd*w{Bre40|QmbNX!5L literal 0 HcmV?d00001 diff --git a/vectors/v1/messages/cast_remove.pb.txt b/vectors/v1/messages/cast_remove.pb.txt new file mode 100644 index 0000000..15dbea9 --- /dev/null +++ b/vectors/v1/messages/cast_remove.pb.txt @@ -0,0 +1,18 @@ +# Wire-format disassembly of the Message (review aid; see README). +Message { + 1 data { # 36 bytes + 1 type: 2 + 2 fid: 1234 + 3 timestamp: 94608000 + 4 network: 1 + 6 cast_remove_body { # 22 bytes + 1: 0x0101010101010101010101010101010101010101 # 20 bytes + } + } + 2 hash: 0xb7d1cd976fb46bf5a6fdbdca32717c8404277e2d # 20 bytes + 3 hash_scheme: 1 + 4 signature: 0x962a31a2614c59c56290c9e6f7ea85bef3248ef7e51c91cdb9bb6d43ef4bfc7f7287cfdadf4a53e836969e324bce4283dbe2a4b5cde33ac61359bad9f0f7a20b # 64 bytes + 5 signature_scheme: 1 + 6 signer: 0x69104ef20c6676aacc9e8c291800d1b7e911e20f85b4066156ea118ace44b8d7 # 32 bytes + 7 data_bytes: 0x080210d2091880b58e2d200132160a140101010101010101010101010101010101010101 # 36 bytes +} diff --git a/vectors/v1/messages/key_add_ed25519.pb b/vectors/v1/messages/key_add_ed25519.pb new file mode 100644 index 0000000000000000000000000000000000000000..52e6c98b57503acb95d2e5f30211c900f3249cca GIT binary patch literal 976 zcmd;D#>^ogaEVi*VQZhR0^=;kY0O*-nF4;Fc+$#Notf98DZy}Y`%A$`{H%2B3muVr0ccKNSKOC&>iwA%XHQr{-7uM^Ur;anY@-JOuU`^EE8we+V~ z3~X*XbUJok%2MK(DC?Ac2R8}Tm6Ew|!s5@QvsQJ7j*FQ~P?b+IT!su?^&s0gpnL5(NGT6<9 zi&`*xF)|8?IC*Jk|KFdiFLv_QX8&Ea-yCjiTPne*x4mjW9BAmli!>cIjHclRB?HfVUx{ylN(j&Hn|#l?6^ zefK@?G)+pm=iAmUo@XT^!Km>6;B|cs zCLxjfNrv0>nGF?}9{&IN`lF=@CpXpXl3-MFNDBTH^(|*K_X#{zvDu>sABnc>rtCjWqxO literal 0 HcmV?d00001 diff --git a/vectors/v1/messages/key_remove_custody.pb.txt b/vectors/v1/messages/key_remove_custody.pb.txt new file mode 100644 index 0000000..fb3b878 --- /dev/null +++ b/vectors/v1/messages/key_remove_custody.pb.txt @@ -0,0 +1,22 @@ +# Wire-format disassembly of the Message (review aid; see README). +Message { + 1 data { # 125 bytes + 1 type: 17 + 2 fid: 1234 + 3 timestamp: 94608000 + 4 network: 1 + 20 key_remove_body { # 110 bytes + 1: 0x0606060606060606060606060606060606060606060606060606060606060606 # 32 bytes + 2: 0x9a7ae0a0284747b8fab028499bfb9195b8f60dd317160c754dbee389356264dc4e225cf4c89b88a05ba0895c91b18da433c7acb24607444ba562cf86ada39e3a1c # 65 bytes + 3: 1 + 4: 99999999 + 5: 2 + } + } + 2 hash: 0x7f9231b62f033121a5c3fff3d7e2a560c9b27cba # 20 bytes + 3 hash_scheme: 1 + 4 signature: 0x6253fa5af0b1543e4524b806b61d037a46a4f55e4fb8487306027c2a8462fd1ce951ddc6ff0ad76ddc51ff3bd06c81b8e3372013bdb45e3e139d1c3173c99208 # 64 bytes + 5 signature_scheme: 1 + 6 signer: 0x69104ef20c6676aacc9e8c291800d1b7e911e20f85b4066156ea118ace44b8d7 # 32 bytes + 7 data_bytes: 0x081110d2091880b58e2d2001a2016e0a20060606060606060606060606060606060606060606060606060606060606060612419a7ae0a0284747b8fab028499bfb9195b8f60dd317160c754dbee389356264dc4e225cf4c89b88a05ba0895c91b18da433c7acb24607444ba562cf86ada39e3a1c180120ffc1d72f2802 # 125 bytes +} diff --git a/vectors/v1/messages/link_add_follow.pb b/vectors/v1/messages/link_add_follow.pb new file mode 100644 index 0000000000000000000000000000000000000000..5bf5672adc18f21ceeb57d626c28f08de8886e41 GIT binary patch literal 180 zcmd;*^?@S$rDma)?XvvEds35=cJXjZKfRV|8==gp3 zwZ_9k5k=WO*5Q@rdmbm|h9@#>Fd8Xj3iy5ENh@1*W?qk`1jEJcF9jd*w{Bre40|Qm Nb^G589^6fl*>`l+@nU@TIOX*vh zv?LVnS@hb4gGWkW@v7`D^Xe8>4Mrn{OaZ@7JZWXC&dlr4lwi2H{iWa|{?;vQiD9n< NyUw}nxNe2pVE`73M_d2^ literal 0 HcmV?d00001 diff --git a/vectors/v1/messages/link_remove_follow.pb.txt b/vectors/v1/messages/link_remove_follow.pb.txt new file mode 100644 index 0000000..2c83754 --- /dev/null +++ b/vectors/v1/messages/link_remove_follow.pb.txt @@ -0,0 +1,19 @@ +# Wire-format disassembly of the Message (review aid; see README). +Message { + 1 data { # 25 bytes + 1 type: 6 + 2 fid: 1234 + 3 timestamp: 94608000 + 4 network: 1 + 14 link_body { # 11 bytes + 1: "follow" # string, 6 bytes + 3: 456 + } + } + 2 hash: 0x1fe5ec1ebf33898d74c9cc106403784d14c48862 # 20 bytes + 3 hash_scheme: 1 + 4 signature: 0xf8aa33e288b6a9e30d5f813e8aad2ace7e98de9f512325e8a79f0d58b95a4d89cbc6ec8cdb99d231fb1a2f3934846071bca2eb44080c1a10a3aa6b8a377b8405 # 64 bytes + 5 signature_scheme: 1 + 6 signer: 0x69104ef20c6676aacc9e8c291800d1b7e911e20f85b4066156ea118ace44b8d7 # 32 bytes + 7 data_bytes: 0x080610d2091880b58e2d2001720b0a06666f6c6c6f7718c803 # 25 bytes +} diff --git a/vectors/v1/messages/reaction_add_like.pb b/vectors/v1/messages/reaction_add_like.pb new file mode 100644 index 0000000000000000000000000000000000000000..16186c6300019572cec61df83ad08e2ccab14056 GIT binary patch literal 216 zcmdGAd`>?6BZyOvinK+qI`jw8?MLBOx?34Q+l`0 zlUWjsN)CTT%s)I7ex~&%Fd*KUGchs$L;dS53u_lKZ)9G2$G5U_-JCZko6qfPoN9jj zU6!0;dpKv`IgW${vc)~GykFnrWY=IcQpgnW`^1x0w(88h9!&{`i`!ocKH_iP!j>5J PO0esk%Z}?-q&O7->m5a9 literal 0 HcmV?d00001 diff --git a/vectors/v1/messages/reaction_add_like.pb.txt b/vectors/v1/messages/reaction_add_like.pb.txt new file mode 100644 index 0000000..50cb5c6 --- /dev/null +++ b/vectors/v1/messages/reaction_add_like.pb.txt @@ -0,0 +1,22 @@ +# Wire-format disassembly of the Message (review aid; see README). +Message { + 1 data { # 43 bytes + 1 type: 3 + 2 fid: 1234 + 3 timestamp: 94608000 + 4 network: 1 + 7 reaction_body { # 29 bytes + 1: 1 + 2 { # 25 bytes + 1: 321 + 2: 0x0202020202020202020202020202020202020202 # 20 bytes + } + } + } + 2 hash: 0xbbe457a26f1099b0d75d9965bcac691bbb4ce49a # 20 bytes + 3 hash_scheme: 1 + 4 signature: 0xfd1437f0e113e62aec51505f430961616ff07febb4a17da203b103a5dc4d7979ae9cecc983ceba819537c7ee6a1e218757098ece0860a01d738cea4bebde0907 # 64 bytes + 5 signature_scheme: 1 + 6 signer: 0x69104ef20c6676aacc9e8c291800d1b7e911e20f85b4066156ea118ace44b8d7 # 32 bytes + 7 data_bytes: 0x080310d2091880b58e2d20013a1d0801121908c10212140202020202020202020202020202020202020202 # 43 bytes +} diff --git a/vectors/v1/messages/reaction_remove_like.pb b/vectors/v1/messages/reaction_remove_like.pb new file mode 100644 index 0000000000000000000000000000000000000000..dbff74abd71798b9264e4d3dd9e7b07a1daf3bcd GIT binary patch literal 216 zcmdGAd`>?6BZyO(x~=ix=Z_(Q~v*hWMWpSif)?p ziCKbC$>H%0lVhjFuauj1IXrqJD8#z3^U~*B-!oNi-!3k__o9zKtt(kw)TcFkGqZSC z!^(rl`P5GOB-XPvUYdOEx(=H^n+BtiLZ*Pp8`<@5jk`KjFU~s%3jVTIbKU=0KezZgX}R?y*17JInZ7g+qjE z+}qu<(ToRF&K{j%)HCN=*h9+`8B7|CMhck%exG>K%2u73*P|)HaB=%f!AJb9Ti6oA PUI})cbJ=m-3ZK&e!k9=7 literal 0 HcmV?d00001 diff --git a/vectors/v1/messages/user_data_add_display.pb.txt b/vectors/v1/messages/user_data_add_display.pb.txt new file mode 100644 index 0000000..d7c6169 --- /dev/null +++ b/vectors/v1/messages/user_data_add_display.pb.txt @@ -0,0 +1,19 @@ +# Wire-format disassembly of the Message (review aid; see README). +Message { + 1 data { # 27 bytes + 1 type: 11 + 2 fid: 1234 + 3 timestamp: 94608000 + 4 network: 1 + 12 user_data_body { # 13 bytes + 1: 2 + 2: "Test User" # string, 9 bytes + } + } + 2 hash: 0x60ee272dd458e0cf081bc3db81a16b26cd56b048 # 20 bytes + 3 hash_scheme: 1 + 4 signature: 0x32787cd875d76c739bdf5e1e4be40fd7552a3dcf5b2cfcb683512cc4469cb831bc3fc88d9a33ce784058455eedbb1d5b01c024cdc598328c9cd656e139c86802 # 64 bytes + 5 signature_scheme: 1 + 6 signer: 0x69104ef20c6676aacc9e8c291800d1b7e911e20f85b4066156ea118ace44b8d7 # 32 bytes + 7 data_bytes: 0x080b10d2091880b58e2d2001620d08021209546573742055736572 # 27 bytes +} diff --git a/vectors/v1/messages/verification_add_eth.pb b/vectors/v1/messages/verification_add_eth.pb new file mode 100644 index 0000000000000000000000000000000000000000..d91bc0f65ab5bf2198ad8bc88bad92c0b2df6c23 GIT binary patch literal 406 zcmd<;WaMBMxWp;Zu(eNDfzhj)ON1E<5OQRt6i6ws5CB3V7j8}p{oD7yd0wSeU|gj5 z24-eELkUJDhq9%j!Si^J`@J~VzUn?#kPzRG%KiQuJ}j~}zx1Fh>WS?CweQ~)oVjNl zznV)j>u$cpbZw0%dFM=L2B$h@ak5-z(_l1G$Q1DV#FJLG>dd?zO$mmJ+g}Pk;&0u; SmKgR*u Date: Thu, 18 Jun 2026 11:50:42 -0500 Subject: [PATCH 2/2] fix(lint): don't lint vectors so they maintain parity with the snapchain copy --- .github/workflows/ci.yml | 2 +- .prettierignore | 5 +++++ CONTRIBUTING.md | 2 +- yarn.lock | 8 ++++---- 4 files changed, 11 insertions(+), 6 deletions(-) create mode 100644 .prettierignore diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f0c0d16..57569fe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,7 +25,7 @@ jobs: - name: Restore cached dependencies for Node modules id: module-cache - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: ${{ github.workspace }}/node_modules key: ${{ runner.os }}--node--${{ hashFiles('**/yarn.lock') }} diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..f28df08 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,5 @@ +# Generated conformance-corpus manifests are produced byte-for-byte by the reference +# implementation (farcasterxyz/snapchain) and copied here verbatim. Reformatting them would +# drift them from the source of truth on every regeneration. The binary .pb / .pb.txt golden +# files aren't matched by the lint glob (**/*.{json,md}), so they need no entry here. +vectors/**/*.json diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6d30135..4876f56 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,7 +9,7 @@ If you're new to Farcaster we recommend joining the Telegram channels and watchi | Medium | Description | | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | | [Announcements Telegram](https://t.me/farcasterxyz) | A channel for major protocol announcements. | -| [Developer Telegram] | A channel for developer Q&A. | +| [Developer Telegram] | A channel for developer Q&A. | | [Dev Call Invitation](https://calendar.google.com/calendar/u/0?cid=NjA5ZWM4Y2IwMmZiMWM2ZDYyMTkzNWM1YWNkZTRlNWExN2YxOWQ2NDU3NTA3MjQwMTk3YmJlZGFjYTQ3MjZlOEBncm91cC5jYWxlbmRhci5nb29nbGUuY29t) | Open Zoom call for developers every other Thursday at 10am PT. | | [Dev Call Agenda](https://warpcast.notion.site/b08fed5cbf884e6a80b3acc2dd0666b2?v=4b51e7442af14b48a69871299c22e288) | Agendas for upcoming and prior dev calls. | | [Dev Call Recordings](https://www.youtube.com/watch?v=lmGXWP5m1_Y&list=PL0eq1PLf6eUeZnPtyKMS6uN9I5iRIlnvq) | Recordings of prior dev calls. | diff --git a/yarn.lock b/yarn.lock index a6073ae..b7c2480 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,7 +2,7 @@ # yarn lockfile v1 -prettier@^2.8.4: - version "2.8.4" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.4.tgz#34dd2595629bfbb79d344ac4a91ff948694463c3" - integrity sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw== +prettier@^2.7.1: + version "2.8.8" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" + integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==