test(cli): end-to-end coverage for witness exchange (export → sign → submit) - #267
Merged
Conversation
The multi-signature flow had unit tests for the blob format but nothing ran the commands themselves. The submit path in particular was migrated to the LEZ v0.2.4 WalletCore API compile-checked only. Add scripts/multisig-e2e-test.sh, which drives the full round trip against a live sequencer. Wallet A exports a partial transaction with --export and --co-signer, wallet B signs it with spel sign and submits it with spel submit, and the transaction must confirm. Both wallets are created from scratch in the work directory, so the flow proves the co-signer needs no key of the exporter. Two failing paths are asserted along the way: submitting while a witness is still missing, and submitting a blob whose message was tampered with after signing. The script starts its own sequencer on port 3044 and never touches a running stack. Add spel-cli/tests/exchange_flow.rs with four binary-level tests for sign and submit failure paths. All four reject before the wallet is touched, so they run without a wallet home or sequencer and stay deterministic. Wire the script into CI as multisig-e2e-test, mirroring the init E2E job with the LEZ tag pinned to the framework's pinned revision. Drop an unused import from exchange.rs.
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
The changes are test/CI-focused, consistent with existing patterns in the repo, and the new coverage directly addresses the stated gaps without introducing behavioral changes.
Pull request overview
Adds comprehensive CLI-level coverage for the multisig witness exchange workflow, ensuring the export → sign → submit round trip is exercised end-to-end against a live LEZ sequencer and that key failure paths are tested deterministically at the binary level.
Changes:
- Adds a new E2E bash script that scaffolds a project, starts a dedicated sequencer, creates two isolated wallets, and validates the full witness-exchange round trip plus key rejection cases.
- Adds new Rust integration tests that execute the real
spelbinary to assertsign/submitreject unreadable blobs, missing witnesses, and tampered messages before wallet initialization. - Extends CI with a dedicated “Multisig E2E” job wired to the shared LEZ build/caching setup.
File summaries
| File | Description |
|---|---|
spel-cli/tests/exchange_flow.rs |
New binary-level integration tests for deterministic spel sign / spel submit failure paths. |
spel-cli/src/exchange.rs |
Removes an unused import (no behavior change). |
scripts/multisig-e2e-test.sh |
New end-to-end script covering export/sign/submit against a live sequencer, including negative-path assertions. |
.github/workflows/ci.yml |
Adds a new CI job to run the multisig E2E script using the existing LEZ setup/caching approach. |
Review details
- Files reviewed: 4/4 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
vpavlin
added a commit
that referenced
this pull request
Sep 7, 2026
Adds a guided tutorial, a five-part reference (CLI, IDL, macros, types, client-gen), and an AgentSkill for agent-driven SPEL work. Verified end to end against a live LEZ v0.2.4 sequencer before publishing: scaffold, the tutorial's program exactly as written, generate-idl, make setup/deploy, initialize, increment, and `spel inspect <PDA> --type CounterState` returning count 5. Content is current with main as of #267, including the parts that landed after this work was first written: - witness exchange: --export, --co-signer, `spel sign`, `spel submit` (#246) - `program-id` (the v0.5.0 rename of `inspect <FILE>`) - --spel-git, and the flag-order rule for `init` (#255) - private PDAs: --npk/--vpk and the v0.2.1 derivation formula (#256) - a Claims section covering rule 7, ClaimedNonDefaultAccount and AccountAlreadyInitialized, and the ClaimedIfDefault a signer now emits (#262) - chained calls as the supported way to touch accounts a program does not own Originally opened as a takeover of #63. Co-Authored-By: Jimmy Claw <jimmy@claw.dev> Co-Authored-By: Vaclav Pavlin <vaclav.pavlin@gmail.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S9qsH6Um6shweCPEN3Z6ph
5 tasks
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.
Description
Closes #263
The witness exchange flow from #246 merged with unit coverage of the blob format but nothing exercised the commands themselves, and the submit path had only been compile-checked since the LEZ v0.2.4 WalletCore migration. This PR adds end-to-end coverage of the full export, sign, submit round trip against a live sequencer, plus deterministic failure-path tests for
spel signandspel submit.The e2e run creates two wallets from scratch. Wallet A exports a partial transaction with
--exportand--co-signer, wallet B signs it withspel signand submits it withspel submit, and the script asserts the transaction confirms in a block. Two failing paths are asserted along the way: submitting while a witness is still missing, and submitting a blob whose message was tampered with after signing. The tamper step flips one bit in the last byte ofmessage_hex, which keeps the blob decodable so the rejection is specifically the signature check.Verified locally against a freshly built LEZ v0.2.4 stack, all steps pass. That run is also the first live execution of the submit path since the v0.2.4 migration, which covers point 3 of the ticket.
Changes
scripts/multisig-e2e-test.sh, modeled on the existing e2e scripts. Starts its own sequencer on port 3044 and only ever kills a leftover process matching that port, never a running stack.spel-cli/tests/exchange_flow.rswith four binary-level tests forsign_commandandsubmit_commandfailure paths. All four reject before the wallet is touched, so they need no wallet home or sequencer.multisig-e2e-test, modeled on the init E2E job with the LEZ tag pinned to the revision fromspel-framework/Cargo.toml.spel-cli/src/exchange.rs.Checklist
cargo build -p spel)cargo test -p spel, 113 tests, plus the e2e script against LEZ v0.2.4)main(not another feature branch)