NUT-18: Payment request consolidation (and extra fees for non-preferred mints)#381
NUT-18: Payment request consolidation (and extra fees for non-preferred mints)#381robwoodgate wants to merge 25 commits into
Conversation
Spec moved from cashubtc/nuts#380 to cashubtc/nuts#381, adding fee_reserve (fr) and supported_methods (sm) alongside the existing mint-strict flag. Adds an isMintListStrict resolver for the spec default-to-true semantic.
|
@callebtc , @thesimplekid - we have three implementations, can we consider final review / merge please. cc @ye0man |
|
4 implementations: |
Spec moved from cashubtc/nuts#380 to cashubtc/nuts#381, adding fee_reserve (fr) and supported_methods (sm) alongside the existing mint-strict flag. Adds an isMintListStrict resolver for the spec default-to-true semantic.
|
The only thing I still don't love about this is the It opens up all kinds of edge case issues as I'd rather default to What are the thoughts on this? |
I agree, I think default true is an anti pattern and we should avoid it. |
Agreed. Would you prefer to keep |
I would flip the semantics. |
yeah, that's my leaning too. @d4rp4t @a1denvalu3, do you agree? |
i agree with this ... |
|
This gives the same semantic, but flipped so an omitted value means |
|
Cashu-TS updated to use new |
Co-authored-by: tsk <tsk@thesimplekid.com>
207e484 to
13e7cc8
Compare
- sm entries become {mn, mf?} objects; mf per-method fee stacks additively with top-level fr
- NUT-26 tag 0x0b promoted to sub-TLV (0x01 method, 0x02 fee)
- regenerate + verify test vectors; fix pre-existing basic vector blob/JSON mismatch
This comment was marked as outdated.
This comment was marked as outdated.
|
CTS updated to use new fee per method: |
| - `mf`: additional fee, in the request unit, the payer MUST add when using this method | ||
|
|
||
| The per-method fee (`mf`) is independent of the top-level fee required for non-preferred mints (`fr`): if the payer sends from a non-preferred mint (outside `m`, `mp` = true) **and** relies on an `sm` method that carries a fee, the payer MUST add both the `fr` and `mf` fees. |
There was a problem hiding this comment.
what is the point of "fr" if there are "mf" fees as well?
There was a problem hiding this comment.
fr is the fee for using a non-preferred mint (mint not in the m list, mp=true)
mf is the fee for using a specific payment method.
This allows fee adds for unknown mints, as well as for using expensive methods.
Example:
// preferred list (mp=true), fr=5, and onchain carries mf=10
pr.amountToSend('https://in-list.mint'); // Amount, base only → 100
pr.amountToSend('https://in-list.mint', 'onchain'); // + mf → 110
pr.amountToSend('https://other.mint', 'bolt11'); // + fr → 105
pr.amountToSend('https://other.mint', 'onchain'); // + fr + mf → 115There was a problem hiding this comment.
I think this is redundant? As presumably the fee for using a non default mint is because they are going to melt out and that fee will be dependent on method so can just include it in the mf? And mf should only apply to mints outside of preferred?
There was a problem hiding this comment.
The thing I'm confused about with the whole per-method fee idea is how the sender knows which method the receiver will use to cash out?
There was a problem hiding this comment.
I think this is redundant?
I think so too.
If the mint is in the list, you should accept the ecash (no method fee applies). If it's a foreign mint, you required a method and a certain fee buffer for that method.
There was a problem hiding this comment.
So what shape would you want to see? If the sender cannot know which method the receiver will use, it seems that fee per method itself seems redundant.
sm can just be a single method string (your mint must support x) and fr the fee as now.
"sm": "bolt11",
"fr": "2",Otherwise, given a menu, the sender is likely to just choose the "cheapest" because they cannot know whether the receiver will offload via bolt11, onchain etc
Alternatively, we can go back to the original multi-list sm (your mint must support at least one of these methods) and a single fr for using the non-preferred mint.
"sm": [ "bolt11", "onchain" ],
"fr": "2",There was a problem hiding this comment.
Some thoughts on this, and the wider payment request needs / issues we've discussed over time:
Fee per method
I suppose a sender is rightfully able to send cheapest per method fee if their chosen mint support 2 or more methods.
So if payment request says:
"sm": [
{ "mn": "bolt11" }, // omitted mf = 0
{ "mn": "onchain", "mf": 50 }
]
And the sender mint supports both, they add no extra mf fee because their mint was compliant with request.
But if a sender's mint is onchain only, they have to pay the lowest per method fee their mint supports (50 in example).
Is that how you envisaged it @callebtc ?
And should the mf per mint fee apply in all cases, or just when using a non-preferred mint?
Fee Required (fr)
I'm not sure the fr is totally redundant. We discussed a case where a sender can use a mint they control with high lightning fees. The fr was an extra fee for using a mint the sender doesn't explicitly trust, regardless of the methods they support.
If the mf fee applies only to non-preferred mint, then I agree, fr is redundant.
Include input fees
Nothing we have discussed so far handles the case where a sender sends a pathological set of proofs - example, 1000 x 1 sat proofs from a mint with 250ppk fee = 250 sats. Which is kind of what I imagined the fr fee would help to mitigate. "If you choose to send from your own mint, add this fee".
Maybe the input fee issue could disappear along with fr by replacing it with an "include fees" boolean, or mandating the amount is net of input fees?
…f (method_fee) is for non-preferred mints only
|
Following discussion in the TS Devs meeting, I've updated the spec as follows: Commit: 7ff7864
Note: Change of spec, implementations will need to be updated if this new direction is agreeableRelated discussion: #381 (comment) cc @callebtc , @thesimplekid , @d4rp4t , @KvngMikey |
Payers must select proofs so the amount received after input fees covers the request. Removes the nf flag and its TLV tag; the supported_method sub-TLV moves to tag 0x0a. Test vectors regenerated.
thesimplekid
left a comment
There was a problem hiding this comment.
Updated cdk to current spec in cashubtc/cdk@b5a5eb4
Drop `fr` and replace `sm: List[str]` with `sm: List[SupportedMethod]` (`mn`, optional `mf`) per cashubtc/nuts#381. NUT-26 tag 0x0a is now a repeatable supported_method sub-TLV (0x01=method, 0x02=fee u64 BE); 0x0b removed. Also fixes a mis-scoped guard error message (tag 0x01 is id, not transport). Byte-verified against frozen spec vectors.
There was a problem hiding this comment.
Nutshell updated to current spec cashubtc/nutshell@91195fd
Consolidates and Supersedes: #355, #380
Summary
Consolidates the two open NUT-18 payment request proposals around mint preferences, strict mint lists, fee signalling, and required mint payment methods.
This PR keeps the existing
mmint list as the single mint-list field, and adds small companion fields to clarify how that list should be interpreted and how the payer compensates the receiver for fees.Changes
sm(supported_method) from feat(nut-18, nut-26): add preferred_mints to payment requests #355 to require that the payer's mint supports at least one listed payment method (e.g.bolt11,bolt12,onchain), now as a list of{mn, mf?}objects. The optional per-method feemfcompensates the receiver for melting out via that method:m, or from any mint ifmis not set; payments from a listed mint carry no per-method feemfamong the listed methods their mint supportsmp(mint_preferred) to signal whether themmint list is strict or preferred (this is a flip frommsin feat: preferred mints #380):false: receiver only accepts proofs from listed mintstrue: listed mints are preferred, but other mints may be acceptedsum(proofs) - input_fee(proofs) >= amount owed, with the input fee computed from the sending mint'sinput_fee_ppk(NUT-02). This protects the receiver from pathological proof sets (e.g. 1000 x 1 sat proofs at 250 ppk costs the receiver 250 sats to swap).Note: earlier revisions had a flat
fr(fee_required) surcharge for non-preferred mints, then annf(net_fees) opt-in flag. Review discussion concludedfrwas redundant oncemfis scoped to non-preferred mints, andnfhad no sensiblefalsecase (no receiver wants to be underpaid by dust), so net-of-input-fees is now the unconditional rule. Both flags have been dropped and thesupported_methodsub-TLV uses tag 0x0a.Rationale
There were overlapping proposals for preferred mints and strict mint lists. Instead of introducing a separate preferred mint list, this keeps the request format minimal:
mremains the mint listmpdefines whether that list is strict or advisorysmlets receivers express the mint capabilities required for the payment flow, with per-method fees that compensate for melting out of a non-preferred mintThis avoids two competing mint-list fields while covering the desired behaviours.