Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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') }}
Expand Down
5 changes: 5 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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. |
Expand Down
4 changes: 4 additions & 0 deletions docs/SPECIFICATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
50 changes: 50 additions & 0 deletions vectors/README.md
Original file line number Diff line number Diff line change
@@ -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<N>/
manifest.json # vector metadata + expected values (hex)
messages/<id>.pb # the encoded protobuf Message for each vector (authoritative bytes)
messages/<id>.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/<id>.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`.
Loading
Loading