fix(DAN-854): recipient is REQUIRED per METHOD, not across the blockchain set - #8
Open
Danny-Devs wants to merge 1 commit into
Open
fix(DAN-854): recipient is REQUIRED per METHOD, not across the blockchain set#8Danny-Devs wants to merge 1 commit into
Danny-Devs wants to merge 1 commit into
Conversation
…hain set fromMppChargeChallenge rejected every Charge request without "recipient", citing the charge-intent spec as its authority. That spec lists recipient under OPTIONAL Fields; the line the message leaned on is a parenthetical illustrating that a method spec MAY elevate it. The mechanism is per-method, and Lightning exercises it in the other direction. Read from each method spec at mpp-specs f9506cd: evm REQUIRED · tempo REQUIRED · solana REQUIRED · stellar REQUIRED lightning OPTIONAL — "the invoice payee is implied by the BOLT11 invoice" Lightning is the lone exception among the five, which is why a blanket rule survived: it is correct four times out of five. The Lightning drafts own canonical example threw before reaching resolveNetwork. payTo for Lightning resolves to methodDetails.invoice, which the spec calls authoritative and from which all other payment parameters derive. Every branch of resolvePayTo returns a payable destination or throws — there is no path that emits an empty string, because requirements carrying payTo:"" look valid and can never settle. Fixes the write-path twin in the same change and off the same table: toMppChargeRequest used the identical blanket set, so it refused to EMIT a spec-legal Lightning charge. Same misreading, opposite direction. Error messages now name the method spec that actually requires the field. The wrong reason is what the next agent acts on. Criterion 5, confirmed not changed: the misreading did not reach "expires". Every reference is to challenge.expires, the auth-param, never request.expires — which is what the charge spec requires. Gates: tsc --noEmit clean · 1111 tests / 29 files pass. No Python MPP compat module exists, so there is no cross-language twin (checked, not assumed).
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
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.
Closes DAN-854.
The defect
fromMppChargeChallengerejected every Charge request lackingrecipient, and the error message cited an authority that says the opposite:draft-payment-intent-charge-00§Shared Fields listsrecipientunder Optional Fields. The line that message leaned on is a parenthetical — "Payment methods MAY elevate OPTIONAL fields to REQUIRED in their method specification (e.g.recipientandexpiresare REQUIRED for blockchain methods)" — which illustrates a mechanism, and that mechanism is per-method. Reading it as a blanket rule lets a prose example in the core document override the method specs that are actually normative.Requirement levels, read from each method's own request schema
tempoxyz/mpp-specs @ f9506cd:recipientdraft-evm-charge-00.md:264draft-tempo-charge-00.md:155draft-stellar-charge-00.md:258draft-solana-charge-00.mddraft-lightning-charge-00.md:206Lightning is the lone exception among the five, which is why the blanket rule survived review — it is correct four times out of five. The Lightning draft's own canonical example threw upstream of
resolveNetwork, at the recipient check.The design question: what does
payTobecome?The BOLT11 invoice.
draft-lightning-charge-00§Method Details makesmethodDetails.invoiceREQUIRED and states "This field is authoritative; all other payment parameters are derived from it." The payee is implied by it, so it is the payment destination.Every branch of
resolvePayToreturns a payable destination or throws. There is deliberately no path that yields""— requirements carrying an emptypayTolook structurally valid and can never be settled, which is strictly worse than rejecting at the boundary. An explicitrecipientstill wins when Lightning supplies one, since OPTIONAL is not forbidden.The write-path twin, fixed in the same change
toMppChargeRequestkeyed off the identical blanket set, so it refused to emit a spec-legal Lightning charge — one carrying an authoritative invoice and no recipient. Same misreading, opposite direction. Both paths now share one table rather than growing a second copy.Criterion 5 — confirmed, not changed
The same misreading did not reach
expires. Every reference is tochallenge.expires, the auth-param, never arequest.expires— which is exactly what the charge spec requires, since request objects MUST NOT duplicate the expiry value.Verification
The assertion that failed before this change, and is the whole of the defect:
Watched failing (3 failed / 6 passed) before the fix, then passing. No Python MPP compat module exists, so there is no cross-language twin — checked, not assumed.
Deliberately not done here
Acceptance criterion 4 asks that the synthetic
recipientworkaround be removed fromtest/compat-mpp-network-resolution.test.ts. That file does not exist onmain— it lives on PR #3's branch (et3rnald/dan-848-mpp-network-resolution), which is still open. It cannot be edited from here without stacking, and a stacked PR runs no CI in this repo (DAN-873): it would show two green Vercel checks while the whole suite sat out. This PR targetsmainso its checks are real. The workaround should be removed when #3 lands; the fix it worked around is now in place.Noted in passing, not in scope
The Lightning draft's 402 example is internally inconsistent: the base64
requestauth-param decodes to"currency":"BTC", while the "Decodedrequest" block directly beneath it reads"currency": "sat"and §Shared Fields states currency MUST be"sat". The base64 appears not to have been regenerated. Neither shape carriesrecipient, so this PR is unaffected. Worth an upstream report.🤖 Generated with Claude Code