Repository navigation
docs(spec): a consumer rule for the R10.2/R10.5 gap, not just the gap itself - #178
stupeterwilliams-ui wants to merge 4 commits into
Conversation
SPEC.md already says scope is primitives only and that FLOP-network settlement "plugs in later as one rail among several". What it never does is name the document that binding satisfies — so someone reading FLOP's yellow paper, whose §10 is a normative HTLC specification with MUST-level requirements, finds no reference to it anywhere in this repository and cannot tell deliberate scope from an oversight. That someone was me, in flop-labs#132. The answer was in SPEC.md's opening paragraph and I asked anyway; @bdunn77 pointed at it, verified both gaps on the exact tree, and proposed this sentence. Their framing. Assigns the two requirements rather than only mentioning them. R10.2's timelock margin is a relationship between a rail's own T_lock and these deadlines, so only a rail that has a T_lock can check it — which is why validateDeadlines supplies no universal default, and why the requirement belongs to the adapter. R10.5's "lock an estimated max, settle the actual" has no tclk/1 shape at all, since amount is fixed on the offer and contractId commits to the offer wholesale; that is a tclk/2 question (flop-labs#57), not a patch. Docs only. check:protocol clean, 104 tests passing. Closes flop-labs#132. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… have §5 said the flop-htlc escrow is opened with an `And[Hash(h), Before(T)]` or `Point(Y)` policy leaf, and that our statement encodings are byte-identical to that escrow's for both halves. Naming the source document in §9 is what made that checkable, and @Qwealzy checked it on this PR: the hash half holds and the point half has nothing behind it. Verified independently against https://flop.finance/intro/yellowpaper/, fetched at 200. §10 R10.1 fixes the lock as H = SHA256(s), redeemable by s before T_lock — a hash-and-timeout leaf, and our 32-byte sha256 digest for Hash is byte-identical to it. §6.1's declarative spend-condition layer lists its predicates as sig, hash, timelock and threshold. PTLC, adaptor, Point( and Schnorr occur zero times in the whole document. So the 33-byte SEC1-compressed point we encode for Point matches nothing published on the FLOP side. That is now stated as the encoding this library would use if such a leaf lands, rather than as a compatibility claim. The rail registry row drops "hash/point" to "hash" for the same reason, and §9's "the interface and encodings are already compatible" is narrowed to the hash lock. This describes the published spec, not the pallet. If a point leaf exists in the implementation and not in the document, the document is where the gap is and I would rather be told than guess. Docs only. check:protocol clean, 104 tests passing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
§9 described R10.2's margin as "a relationship between a rail's own T_lock and these deadlines". That is not what the requirement says. R10.2 is T_FLOP >= T_other + max(ceil(T_other × p / 100), max_finality_stall + current_finality_lag), so evaluating it needs the counter-chain's own duration and three live FLOP chain parameters — not a rail's T_lock alone. The conclusion is unchanged and stronger: nothing that cannot read chain state at lock time can check this, which is precisely why validateDeadlines supplies no universal default. The error originates in flop-labs#132, where I block-quoted R10.2 as "T_FLOP > T_other with margin (2 h FLOP, 1 h counter-chain)" and called those concrete constants. The constants were mine. That issue body is corrected in place with the change marked, and @yonelpyc — who was reasoning from it — has the detail on the thread. Also sharpens the R10.5 note. "amount is fixed on the offer" understates it: amount occurs once in the entire frame schema, on OfferFields, and no lock, reveal, refund or receipt frame carries one. A settled actual cannot be expressed, or recorded after the fact as commentary. That is a stronger statement of why R10.5 has no tclk/1 shape, and it answers the schema question @yonelpyc asked. Docs only. check:protocol clean, 104 tests passing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… itself @boomelant's read of the yellow paper's §12.1 on flop-labs#132 is accurate — inference settles through pallet_compute_channel (open_channel -> settle/force_settle), not through a fixed tclk/1 amount, and R4.4 gives G_n its own fixed-width accounting that a tclk decimal has no business standing in for. §9 already named the gap; it didn't say what a consumer should do about it in the meantime. It does now: amount is a ceiling, not G_n or proof of settlement, and room claimed/receipt is agreement, not completion — §1 already draws that line, this just applies it to the FLOP-inference case specifically. Verified §12.1, R4.4 and R10.5's text directly against the published yellow paper before writing this, rather than trusting the paraphrase. pnpm -r --include-workspace-root build && test: 177 passed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
boomelant
left a comment
There was a problem hiding this comment.
PUI consumer review: the guidance is directionally right and useful, especially the separation of room coordination from rail-authoritative inference settlement. One wording edge is worth tightening before this becomes normative consumer guidance: calling generic tclk/1 amount a coordination ceiling can itself be read as a protocol invariant (actual <= amount) even though tclk/1 has no FLOP rail binding or variable-settlement semantics that enforce that relationship. For a generic consumer, amount is the negotiated amount/term; it is only a reservation/maximum when a specific rail profile explicitly defines it that way. Suggested wording: “Do not interpret generic tclk/1 amount as measured G_n or proof of settlement. A FLOP rail profile MAY define it as a reservation/maximum; if so, the rail observer must authoritatively report locked max and actual settlement and enforce actual <= max.” This keeps the safe rule from #132 without accidentally standardizing FLOP semantics into the rail-agnostic field.
Closes the other half of #132: @boomelant's read of the yellow paper's §12.1 is accurate (verified against the published text directly — inference settles through
pallet_compute_channel'sopen_channel→settle/force_settle, and R4.4 givesG_nits own fixed-width accounting), and their four-point "conservative consumer rule" is worth having in the spec itself rather than only in an issue comment.§9 already named the R10.2/R10.5 gap (#138, not yet merged — this branch stacks on it, so the diff includes those three commits until it lands). What it didn't say is what a consumer should do about the gap in the meantime. This adds that: a tclk/1 offer
amountis a coordination ceiling, never measuredG_nor proof of settlement; roomclaimed/receiptis agreement, not completion (§1 already draws that line, this applies it to the FLOP-inference case); and a future rail observer implementing R10.5 needs to return both the locked max and the rail-authoritative actual, which tclk/1 doesn't need to carry itself.Docs-only, one problem,
SPEC.md§9 + aCHANGELOG.mdentry.pnpm -r --include-workspace-root build && test: 177 passed.