feat(tlsn): generate the ceremony session fixtures the contracts verify - #19
Merged
Merged
Conversation
An example that builds the four launch records the way a ceremony builds them minus the MPC: each request composed as the browser or the Token-Exchange Service composes it and driven through hyper's http1 client, the encoder under tlsn's prover, against a scripted platform; the layouts this workspace computes; tlsn's own SHA-256 plaintext hashes as commitments; `AttestedData::from_observed`, the notary's path; and an EIP-191 signature over the record's keccak by anvil #0, the key the contract suites trust. The PKCE verifier inside is derived from the digest the contracts derive on their test chain, ported here field for field, so the records verify with their signatures unedited and a drift in the port fails the contract test by name rather than passing on a patched body. Deterministic -- fixed clock, blinders and bodies -- so the files can be regenerated and compared. libid-contracts carries them under test/fixtures and reads the claim out of each. Assisted-by: Claude Opus 5 Signed-off-by: xgreenx <xgreenx9999@gmail.com>
GitHub pretty-prints its identity response for the media type the profile pins: a space after every colon, a newline and an indent before every key. The finders matched `\"login\":\"` and `\"id\":` byte for byte, so no layout for a real GitHub identity read could be built, and the same template the verifier refused was refused here first, with the reason invisible. The key, then a colon, then the value, with JSON whitespace allowed on either side of the colon and before an integer's terminator. The whitespace is inside the member: the verifier reads the revealed range as the wire carried it and removes the whitespace beside structure itself before comparing, so the range has to carry it. A key that is only another member's value is passed over, as the old template passed it over. `123 4` is still not a number. The verifier side is libid-org/libID-contracts#37. Assisted-by: Claude Opus 5 Signed-off-by: xgreenx <xgreenx9999@gmail.com>
…o feat/ceremony-fixtures
…serves The canned /user body was compact, composed from the documented shape. GitHub pretty-prints it for the media type the profile pins -- a newline and two spaces before every member, a space after every colon -- and a fixture without that whitespace passed a verifier that refused every real read. The formatting is the platform's, and the fixture now carries it, which the finders of the merged whitespace change lay out with the whitespace inside each revealed member. Assisted-by: Claude Opus 5 Signed-off-by: xgreenx <xgreenx9999@gmail.com>
The generator reproduces what the platforms send; this records it. A real MPC-TLS session against the real platform, the verifier in this process on the other end of a pipe, signing as anvil #0, so the records verify under the contract suites with their signatures unedited. The PKCE challenge is derived from the same Authorization Digest the suites derive, which is what binds the platform's token to that submission. The operator supplies the app and the consent: a redirect URI on the app pointing at this tool's listener, then the URL it prints, opened and consented to. It receives the code, runs the token session and then the identity session, and writes `<platform>-ceremony-real.json` in the generated fixtures' format. The bearer, the secret and the code are not written: the record commits the first two and the third is spent. The derivations both examples share -- the digest, the verifier, the challenge, the submission header -- move into a module both include. Smoke-tested with a bogus client: the listener, the URL and the session up to GitHub's answer all work; the run stops on the platform's error with the verifier stopped first. Assisted-by: Claude Opus 5 Signed-off-by: xgreenx <xgreenx9999@gmail.com>
…rror The previous commit described this and did not carry it: a scripted edit missed the formatted text and the build went ahead without it. On a failed session the prover's error now aborts the verifier task and is awaited before the tool exits, so the runtime is not torn down under a live session, which is what produced a second panic in the smoke test. Assisted-by: Claude Opus 5 Signed-off-by: xgreenx <xgreenx9999@gmail.com>
`unwrap_or_else(fail)` does not coerce a function returning `!` to the value type; a closure does. The previous commit was pushed on a chain that did not gate on the build, which this one does. Assisted-by: Claude Opus 5 Signed-off-by: xgreenx <xgreenx9999@gmail.com>
The lockfile moved when the examples gained sha2, hex and libid-crypto as dev-dependencies and was never staged; CI regenerated it silently. Assisted-by: Claude Opus 5 Signed-off-by: xgreenx <xgreenx9999@gmail.com>
Merged
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
An example binary,
cargo run -p libid-tlsn --example ceremony_fixtures -- <dir>, that writesx-ceremony-session.jsonandgithub-ceremony-session.json: two signed records per platform, built the way a ceremony builds them minus the MPC.buildTokenRequest,buildIdentityRequest,identityRequeston libidfeat/ceremony-rebuild-plan) and the Token-Exchange Service (libid-server-rs) compose them, and driven throughhyper::client::conn::http1, the encoder under tlsn's prover, against a scripted platform answering as X and GitHub answer.libid_transcript::ceremony's; the commitments are tlsn's SHA-256 plaintext hashes with fixed blinders; the record isAttestedData::from_observed, the notary's own path; the signature is EIP-191 over the record's keccak by anvil #0, the key the contract suites trust.CeremonyAuthorization.digestForcomputes it on the test chain (domainlibid.claim-identity, version 1, chain 31337, nonce0x55…,abi.encode(address(0xBEEF))), ported field for field, so the records verify with their signatures unedited.Deterministic: fixed clock, blinders and bodies. libid-contracts#35 carries the generated files under
solidity/contracts/ceremony/test/fixtures/and each platform suite verifies its two records and reads the claim out; the digest assertion there is what catches a drift in the port.What this does not cover: the MPC itself and the platforms' own bytes. Those need a real session, which Heorhii's bridge run produces and which would slot into the same files.
🤖 Generated with Claude Code