Skip to content

Commit 05be984

Browse files
tclaude
andcommitted
feat(l2ps): negotiate-sealed-envelope — commit-then-reveal sealed bids (SR-4)
RFQ was the only negotiation mode SR-4 shipped; the brief requires two. This adds `negotiate-sealed-envelope` (DACS-3 §8.4.3): a two-phase sealed-bid exchange where every bid is locked before any is opened, so no participant can see another's number and shade its own. `SealedEnvelopeSession` mirrors `RfqSession` — a pure protocol state machine over the existing channel layer (which already verifies signature, membership, channelId, and monotonic sequence). Commit phase: each participant broadcasts a hiding commitment `sha256(dacs-sealed-envelope:v1: || JCS({bid, salt}))` with a 32-byte random salt. It auto-advances to the reveal phase once every participant has committed (or `closeCommitPhase()` at a deadline). Reveal phase: each opens `{bid, salt}`; the session recomputes the commitment and binds the revealer to exactly what it sealed. The fairness rule is enforced as channel-fatal: a reveal that arrives before the commit phase closes is rejected — otherwise a laggard could adapt its bid to a number it should not yet see. Cheating is contained, not fatal: a reveal whose bid does not reproduce its commitment, or a committer who never reveals, is disqualified (visible in the outcome), so one bad actor cannot sink an otherwise-valid auction. Winner selection is impl-defined via an optional `compareBids` comparator, exactly as RFQ leaves `terms` opaque. Tests: 13, covering the happy path + winner, bids staying hidden until reveal (structural, not a flaky substring check), the early-reveal rejection, the commitment-mismatch and no-show disqualifications, both deadline paths, the non-participant/duplicate/out-of-phase guards, and abort propagation. SPEC NOTE: §8.4.3 of DACS-3-NEGOTIATE.md was not available in-repo when this was written. The commit-then-reveal mechanism is unambiguous and implemented faithfully, but the exact wire field names and the domain string should be reconciled against §8.4.3 before this is treated as spec-final. Flagged in the module header. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent d3620ae commit 05be984

3 files changed

Lines changed: 714 additions & 0 deletions

File tree

src/l2ps/channel/index.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,17 @@ export {
7878
type RfqLike,
7979
type ChannelSessionView,
8080
} from "./finalize"
81+
82+
export {
83+
SealedEnvelopeSession,
84+
commitmentHex,
85+
SEALED_ENVELOPE_DOMAIN_PREFIX,
86+
type SealedEnvelopeState,
87+
type SealedEnvelopeOutcome,
88+
type SealedEnvelopeSessionOpts,
89+
type SealedCommitBody,
90+
type SealedRevealBody,
91+
type SealedAbortBody,
92+
type SealedCommitment,
93+
type RevealedBid,
94+
} from "./sealedEnvelope"

0 commit comments

Comments
 (0)