Skip to content

Commit 14a0767

Browse files
committed
sdk/swaps: Reject channel receive type in pay quotes
Ark-channel settlement identifies a completed receive and is not a valid pay-side swap quote. Reject it explicitly in preview and execution validation so every settlement enum has deliberate semantics.
1 parent 13c21af commit 14a0767

2 files changed

Lines changed: 43 additions & 0 deletions

File tree

sdk/swaps/in_swap_quote.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,10 @@ func validateInSwapPreview(invoice string, quote *InSwapQuote,
164164
expectedAmountSat := expectedInvoiceSat + quote.FeeSat
165165
switch quote.SettlementType {
166166
case "", SettlementTypeLightning, SettlementTypeInArk:
167+
case SettlementTypeArkChannel:
168+
return fmt.Errorf("ark channel settlement is not valid for " +
169+
"pay quotes")
170+
167171
case SettlementTypeCredit:
168172
expectedAmountSat = 0
169173

@@ -232,6 +236,10 @@ func validateInSwapQuote(invoice string, maxFeeSat uint64, cfg *InSwapConfig,
232236
expectedAmountSat := amountSat + cfg.FeeSat
233237
switch cfg.SettlementType {
234238
case "", SettlementTypeLightning, SettlementTypeInArk:
239+
case SettlementTypeArkChannel:
240+
return fmt.Errorf("ark channel settlement is not valid for " +
241+
"pay quotes")
242+
235243
case SettlementTypeCredit:
236244
if cfg.Preimage == nil {
237245
return fmt.Errorf("credit in-swap config missing " +

sdk/swaps/in_swap_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,41 @@ func TestValidateInSwapPreviewAllowsCreditOnlyZeroAmount(t *testing.T) {
363363
require.NoError(t, err)
364364
}
365365

366+
// TestInSwapValidationRejectsArkChannelSettlement verifies the receive-only
367+
// settlement result cannot be supplied as a pay-side quote.
368+
func TestInSwapValidationRejectsArkChannelSettlement(t *testing.T) {
369+
t.Parallel()
370+
371+
serverPriv, err := btcec.NewPrivateKey()
372+
require.NoError(t, err)
373+
374+
preimage, err := NewPreimage()
375+
require.NoError(t, err)
376+
invoice := testValidPayInvoice(t, preimage)
377+
378+
quote := &InSwapQuote{
379+
PaymentHash: preimage.Hash(),
380+
InvoiceAmountSat: testInSwapInvoiceSat,
381+
AmountSat: testInSwapAmountSat,
382+
FeeSat: testInSwapFeeSat,
383+
Expiry: time.Now().Add(time.Minute),
384+
SettlementType: SettlementTypeArkChannel,
385+
}
386+
err = validateInSwapPreview(
387+
invoice, quote, &chaincfg.RegressionNetParams,
388+
)
389+
require.ErrorContains(t, err, "not valid for pay quotes")
390+
391+
cfg := testInSwapConfig(
392+
serverPriv.PubKey(), preimage, time.Now().Add(time.Minute),
393+
)
394+
cfg.SettlementType = SettlementTypeArkChannel
395+
err = validateInSwapQuote(
396+
invoice, testInSwapFeeSat, cfg, &chaincfg.RegressionNetParams,
397+
)
398+
require.ErrorContains(t, err, "not valid for pay quotes")
399+
}
400+
366401
// TestValidateInSwapQuoteRejectsServerMismatches verifies the client treats
367402
// the swap server response as a quote that must match the caller's invoice.
368403
func TestValidateInSwapQuoteRejectsServerMismatches(t *testing.T) {

0 commit comments

Comments
 (0)