Unit: RFP-003 hard requirements (Functionality, Usability, Reliability, Performance, Supportability, Demos) traced to the tree at commit 98f492ad.
Proof branch: bork/proof/20260924T045832-64864e — check out this branch to run every repro on the exact tree the findings were proved on.
Hunt id: 20260924T045832-64864e (finding ids below abbreviate to /<n>).
Result: 11 confirmed / 3 disputed / 1 unconfirmed (15 findings total across both passes).
Disclaimer**: T**he issues found in this report are coming from a source code level scan done by QA AI tools and there might be some false positives among them.
Two independent passes ran over the unit. The first pass (claude) raised findings /1–/14 with a requirement trace; the second pass (codex) re-ran every repro, re-read the cited code, issued a verdict per finding, and raised one new finding (/15), which the merge pass adjudicated by re-running its four-test repro and re-reading the coordinator transitions it cites — all four tests fail as claimed, so /15 is confirmed.
Findings with a failing test under the owning crate’s tests/: /1 (crates/swap-core/tests/spec_64864e_1.rs), /2 (crates/zec-swap-sdk/tests/spec_64864e_2.rs), /3 (crates/maker-node/tests/spec_64864e_3.rs). Finding /15’s failing test ships as a standalone package at test/20260924T045832-64864e/15/funding_regressions.rs (raised by the second pass; it depends on the unchanged lez-swap-core crate rather than living under crates/swap-core/tests/). All other findings are prose/artifact-only — they concern missing documents, packaging defaults, media, submission artifacts, or spec wording, and are marked as such in their sections.
One row per hard requirement, numbered in specification order within each group. pass means the implementing code was located and matches the spec sentence at its normal path and boundaries; a finding id means a divergence was raised. The trace is the first pass’s; the merge pass joins each finding reference to its final status.
| Req | Requirement (abbrev.) | Where implemented | Verdict |
|---|---|---|---|
| F1 | No central server; offers over Logos Delivery, coordination over Logos Chat | crates/maker-node/src/btc_chat.rs:227-255, xmr_chat.rs:88-95, zec_chat.rs:13-115; crates/node-common/src/run_local_delivery.rs; ADRs docs/architecture/0210, 0211 | pass — no hardcoded central endpoints found in the chat/delivery paths; negotiation terminates in durable local actor registration before any on-chain effect |
| F2 | BTC via BIP-340 adaptor + Taproot; cooperative claim is key-path with no script footprint; refund pre-signed key-path or CSV tapleaf | claim: crates/btc-swap-sdk/src/transaction.rs:136-155, 210-226 (taproot_key_spend_signature_hash, one 64-byte witness item, no annex); refund: crates/btc-swap-sdk/src/p2tr.rs:234-247 (single CSV tapleaf, the spec’s recommended default); MuSig2/BIP-341 tweak: crates/adaptor-signature/src/lib.rs:120-128, pinned at btc-swap-sdk/src/agreement_v1.rs:2087-2088, 2345-2358 | pass — refund fee frozen at negotiation (CPFP-only bumping) and zero CSV slack noted as observations, not divergences |
| F3 | XMR via Ed25519 adaptor + cross-curve DLEQ (h4sh3d/COMIT); atomicity via spend-key share, no Monero scripting | DLEQ: crates/xmr-swap-sdk/src/cross_curve.rs:15-306 (sigma_fun dl_secp256k1_ed25519_eq, verify-on-construct); pre-lock verification: xmr-swap-sdk/src/agreement_v1.rs:916-948; key-share reconstruction from finalized LEZ signature: shared_spend.rs:233-268, xmr-reference-actor/src/lib.rs:3688-3727; plain 1-key Monero address, no scripting: shared_spend.rs:161-172, xmr-monero-adapter/src/wallet_effect.rs:442-481 | pass — construction is the cited COMIT protocol; spec wording drift filed as /12 (unconfirmed); only the LEZ-first direction is supported (documented, ADR 0008) |
| F4 | ZEC transparent via BIP-199 HTLC (OP_IF/OP_SHA256/OP_CLTV/OP_CHECKSIG); Zcash refund deadline strictly after LEZ by a documented margin | script: crates/zec-swap-sdk/src/lib.rs:205-244 (byte-pinned in tests/bip199_contract.rs); transparent-only: agreement_v1.rs:276-294, 1760-1765; deadline machinery: swap-core/src/lib.rs:218-324, zec-swap-sdk/src/profile.rs:213-239, agreement_v1.rs:2199-2221; documented margin: docs/milestone-1/parameter-profiles.md:70-106 | script/addresses pass; deadline-ordering enforcement /1 (confirmed), /2 (confirmed) |
| F5 | Risc0 escrow locks per-chain proof, releases on valid proof, refunds depositor after timelock | compat/lez-v0.2-provisional/escrow/src/lib.rs (preimage 153-165, aggregate witness 167-191, XMR dual-adaptor 199-239; claim windows ..refund_at, refund windows refund_at.., e.g. 938, 1021); guests include the same contract (methods/guest/src/bin/zec_escrow_v02.rs) | pass — claim window exclusive / refund inclusive at refund_at is coherent with swap-core’s observed >= deadline (lib.rs:414-424) |
| F6 | Atomicity: both complete or both refund; no one-sided state | crates/swap-core/src/lib.rs phase machine (753-1348); property tests crates/swap-core/tests/transition_properties.rs; fuzz/fuzz_targets/coordinator.rs | pass for BTC/ZEC at the trace’s boundaries; XMR punish path vs the absolute sentence /13 (confirmed); the second pass additionally raised /15 (confirmed) against this row — the coordinator loses independent funding regressions and authorizes claims from BothLegsLocked with a leg absent or underconfirmed |
| F7 | Native + custom tokens via ATAs | escrow token surface: compat/lez-v0.2-provisional/escrow/src/lib.rs:279-288 (ata_core derivation), 613-668, 1027-1234 (initialize/fund/claim/refund token, witnessed variants 1240-1328); recursive_tokens.rs test; compat/lez-v0_2-sidecar/src/vault_claim_prepare.rs | pass |
| F8 | Pricing: local config + external feed via C API; pluggable sources | local: crates/maker-node/src/price_source.rs:102-119, CLI lez-maker-cli.rs:42-75; C-API worker: crates/logos-price-c-api/src/lib.rs:256-385, adapter crates/maker-node/src/logos_price_source.rs:30-177, wired at lib.rs:1571-1585, 1621-1651 | both modes pass (CLI satisfies the config-or-CLI disjunct); pluggability gap /11 (disputed — the second pass reads the C-API module boundary as the pluggability seam F8 asks for**)** |
| F9 | Headless maker: pairs, prices, feed, advertisement, execution, monitoring; fully CLI-operable | daemon crates/maker-node/src/bin/lez-maker-node.rs; supervisor actor_supervisor/runtime.rs; CLI coverage below (U3) | pass |
| Req | Requirement (abbrev.) | Where implemented | Verdict |
|---|---|---|---|
| U1 | Dedicated full-lifecycle SDK per pair | crates/btc-swap-sdk, crates/xmr-swap-sdk, crates/zec-swap-sdk over crates/swap-sdk-core | pass |
| U2 | Maker daemon + systemd unit + documented install steps | unit packaging/systemd/lez-maker-node.service (sd_notify wired at lez-maker-node.rs:608); installer scripts/install-maker-node-service.sh | unit pass; install documentation absent, chat gateway unpackaged /6 (confirmed) |
| U3 | Maker CLI: pairs/prices, start/stop, history, manual claim/refund over IPC/RPC | crates/maker-node/src/bin/lez-maker-cli.rs (History :297-301, Claim :331-344, Refund :345-358 over the owner UDS; Start/Stop via systemctl, node-common/src/service_control.rs:27-29) | pass (start/stop shell out to systemctl rather than IPC — defensible; stale “Zcash” doc-comment on the pair-neutral Claim at lez-maker-cli.rs:157) |
| U4 | Taker CLI: discovery, initiation, monitoring, claim, refund | crates/taker-node/src/bin/lez-taker-cli.rs (discovery/accept flags :88-112; LifecycleCommand Monitor/Claim/Refund :213-227) | pass |
| U5 | Maker mini-app GUI in Basecamp | apps/basecamp/maker (QML), build instructions apps/basecamp/README.md | pass (BTC scope; health display shows a route count only, noted under /4) |
| U6 | Taker mini-app GUI as primary taker interface | apps/basecamp/taker; docs/m6-zec-reconciliation.md:10 | BTC-only /14 (confirmed) |
| U7 | SPEL IDL for the escrow program(s) | compat/spel-zec-escrow (PROGRAM_IDL_JSON, tests/generated_client.rs:44-45 + snapshot) | pass |
| U8 | Bitcoin Core testnet setup guide, self-hosted + public | docs/bitcoin-testnet4-setup.md (Route A self-host :76, Route B public gateway :238, wallet/funding :179) | pass |
| U9 | Monero node stagenet setup guide, self-hosted + public | — (no such document exists) | /7 (confirmed) |
| U10 | Zcash node testnet setup guide, self-hosted + public, transparent wallet + funds | docs/zcash-testnet-setup.md (self-hosted Zebra :63, public provider :142, wallet/funds :169) | pass |
| Req | Requirement (abbrev.) | Where implemented | Verdict |
|---|---|---|---|
| R1 | Taker-first: maker must not lock until taker lock confirmed | crates/swap-core/src/lib.rs:1072-1113 (observe_maker_lock_impl returns TakerLockNotConfirmed before Phase::TakerLockConfirmed); tests crates/swap-core/tests/e2e_swap_lifecycle.rs, transition_properties.rs | pass |
| R2 | On-chain-only execution after first lock | post-lock engine crates/maker-node/src/actor_supervisor/runtime.rs (no chat/delivery references); claims/refunds not health-gated (lib.rs:1376,1463 gate only quote/publish); daemon runs with no Delivery/Chat configured (lez-maker-node.rs:1200-1212); XMR refund selection chain-evidence-only (xmr-reference-actor/src/maker_refund_activation.rs:1-4) | pass (note: BTC lifecycle config requires a delivery directory, lez-maker-node.rs:147-151 — a local directory, not a live service dependency) |
| R3 | Graceful degradation: start with unavailable chains disabled and reported | crates/maker-node/src/route_health.rs; lib.rs:1196-1262; packaging/systemd/lez-maker-node.json.example | /3 (confirmed) (all-or-nothing startup), /4 (confirmed) (shipped default never reports) |
| R4 | Swap state persistence; resume after crash without fund loss | crates/swap-store/src/lib.rs:1487-1502 (WAL, synchronous=FULL, inode checks); resume-before-readiness lez-maker-node.rs:434-442; tests swap-store/tests/restart_recovery.rs, btc_recovery.rs, zec_sdk_recovery.rs; maker-node/tests/daemon_actor_supervisor_process.rs | pass (resume requires the –actor-supervisor flag, which packaging sets) |
| R5 | Concurrent swap isolation | per-swap SwapCoordinator (swap-core); store isolation tests (swap-store/tests/xmr_effect_workflow_concurrency.rs); ADR 0041 | pass |
| R6 | Timelocks account for variance/congestion/drift; parameters documented with rationale | docs/milestone-1/parameter-profiles.md:70-106; profiles zec-swap-sdk/src/profile.rs:72-96; BTC coupling btc-role-lifecycle/src/config.rs:152-185 | documented pass; ZEC enforcement gap cross-ref /2 (confirmed) |
| R7 | BTC refund construction chosen and justified | docs/architecture/0009-bitcoin-refund-path.md (selects script-path CSV, the spec’s recommended default, with trade-off discussion; presigned failure-mode enumeration not required since presigning was not chosen) | pass |
| R8 | Delivery/Chat outage handled gracefully and documented | chat outbox node-common/src/logos_chat_gateway.rs:473-628; delivery reconcile maker-node/src/lib.rs:1278-1282; degraded flag rpc_contracts.rs:59-63 | partial /5 (disputed — the second pass holds R8’s “degraded mode” is satisfied and rejects the divergence**)** |
| Req | Requirement (abbrev.) | Where implemented | Verdict |
|---|---|---|---|
| P1 | Compute units per escrow op, testnet version noted | docs/lez-compute-units.md:1-30 (measured against LEZ testnet 0.2 v0.2.4, per-instruction cycle table, drift-guard test compat/lez-v0.2-provisional/escrow/methods/tests/escrow_cycles.rs) | pass (BTC-pair instruction variants measured; preimage/XMR variants noted as smaller) |
| Req | Requirement (abbrev.) | Where implemented | Verdict |
|---|---|---|---|
| S1 | Escrow deployed/tested on LEZ testnet 0.2 | docs/lez-compute-units.md:3-4 (program c22d61fc…, deployed block 10566, v0.2.4); submission/EVIDENCE.md | pass |
| S2 | Standalone-sequencer e2e included in CI | .github/workflows/ci.yml (no sequencer job); node-e2e.yml:9-11 (dispatch-only); upstream-compatibility.yml:3-6 (weekly) | /8 (disputed — the second pass holds scheduled/dispatch workflows are still CI**)** |
| S3 | CI green on default branch | .github/workflows/ci.yml | not verifiable from this container (no remote CI state) — needs external node; traceability self-reports “remote branch pending” (docs/requirements-traceability.md:67) |
| S4 | Every hard F/U/R/P requirement has a test | scripts/check-requirements-traceability.sh + docs/requirements-traceability.md | guard passes structurally; acceptance tests self-reported incomplete — the concrete gaps are findings /1–/5 rather than a separate row-level finding |
| S5 | Reference integration per chain, complete e2e swap | crates/btc-reference-actor, crates/xmr-reference-actor, crates/zec-reference-actor + compat/lez-standalone-e2e | pass (BTC exercised on real nodes; XMR/ZEC via local PoC harnesses) |
| S6 | README: deployment, addresses, prerequisites, maker/taker CLI + mini-app usage | README.md (run locally :41, swap walkthrough :90, layout :197) | pass with note — depth is BTC-centric; per-chain prerequisites for XMR partly gated on /7 |
| S7 | Write-up: protocols, escrow, atomicity, timelocks, assumptions, limitations | docs/milestone-1/protocol-design.md, docs/architecture/system-architecture.md, submission/LIMITATIONS.md | pass with note — XMR punish stranding not covered in LIMITATIONS.md, cross-ref /13 (confirmed) |
| S8 | Full API docs per SDK with lifecycle examples | CI “Reject Rust documentation warnings” (ci.yml:144); SDK doc comments | pass structurally (doc-warning gate); packet-level coverage not re-audited |
| S9 | Doc packet per pair SDK | — | /10 (confirmed) |
| S10 | Doc packets for maker CLI and taker CLI | — | /10 (confirmed) |
| S11 | Figma or equivalent designs for both mini-apps | apps/m6-prototypes (clickable maker.html/taker.html prototypes) | pass (“or equivalent”) |
| S12 | Third-party review of on-chain programs/scripts, report in submission | — (submission/ has no review report) | /10 (confirmed) |
| S13 | Third-party review of protocol implementation, report in submission | — | /10 (confirmed) |
| Req | Requirement (abbrev.) | Where implemented | Verdict |
|---|---|---|---|
| D1 | Per chain: happy, refund/timeout, concurrent recordings (9 total) | media/ (BTC happy-path footage only) | /9 (confirmed) |