|
9 | 9 | "time" |
10 | 10 |
|
11 | 11 | "github.com/lightningnetwork/lnd/clock" |
| 12 | + "github.com/lightningnetwork/lnd/fn" |
12 | 13 | "github.com/lightningnetwork/lnd/lntypes" |
13 | 14 | "github.com/lightningnetwork/lnd/lnwire" |
14 | 15 | "github.com/lightningnetwork/lnd/queue" |
@@ -74,6 +75,11 @@ type RegistryConfig struct { |
74 | 75 | // KeysendHoldTime indicates for how long we want to accept and hold |
75 | 76 | // spontaneous keysend payments. |
76 | 77 | KeysendHoldTime time.Duration |
| 78 | + |
| 79 | + // SettlementInterceptor is a service that intercepts invoices during |
| 80 | + // the settlement phase, enabling a subscribed client to determine the |
| 81 | + // settlement outcome. |
| 82 | + SettlementInterceptor *SettlementInterceptor |
77 | 83 | } |
78 | 84 |
|
79 | 85 | // htlcReleaseEvent describes an htlc auto-release event. It is used to release |
@@ -998,6 +1004,41 @@ func (i *InvoiceRegistry) notifyExitHopHtlcLocked( |
998 | 1004 | ) |
999 | 1005 |
|
1000 | 1006 | callback := func(inv *Invoice) (*InvoiceUpdateDesc, error) { |
| 1007 | + // Provide the invoice to the settlement interceptor to allow |
| 1008 | + // the interceptor's client an opportunity to manipulate the |
| 1009 | + // settlement process. |
| 1010 | + var interceptSession fn.Option[InterceptSession] |
| 1011 | + if i.cfg.SettlementInterceptor != nil { |
| 1012 | + clientReq := InterceptClientRequest{ |
| 1013 | + ExitHtlcCircuitKey: ctx.circuitKey, |
| 1014 | + ExitHtlcAmt: ctx.amtPaid, |
| 1015 | + ExitHtlcExpiry: ctx.expiry, |
| 1016 | + CurrentHeight: uint32(ctx.currentHeight), |
| 1017 | + Invoice: *inv, |
| 1018 | + } |
| 1019 | + interceptSession = |
| 1020 | + i.cfg.SettlementInterceptor.Intercept(clientReq) |
| 1021 | + } |
| 1022 | + |
| 1023 | + // If the interceptor service has provided a response, we'll |
| 1024 | + // use the interceptor session to wait for the client to respond |
| 1025 | + // with a settlement resolution. |
| 1026 | + interceptSession.WhenSome(func(session InterceptSession) { |
| 1027 | + log.Debug("Waiting for client response from " + |
| 1028 | + "settlement interceptor session") |
| 1029 | + |
| 1030 | + select { |
| 1031 | + case resp := <-session.ClientResponseChannel: |
| 1032 | + log.Debugf("Received settlement interceptor "+ |
| 1033 | + "response: %v", resp) |
| 1034 | + ctx.SkipAmountCheck = resp.SkipAmountCheck |
| 1035 | + |
| 1036 | + case <-session.Quit: |
| 1037 | + // At this point, the interceptor session has |
| 1038 | + // quit. |
| 1039 | + } |
| 1040 | + }) |
| 1041 | + |
1001 | 1042 | updateDesc, res, err := updateInvoice(ctx, inv) |
1002 | 1043 | if err != nil { |
1003 | 1044 | return nil, err |
@@ -1051,6 +1092,8 @@ func (i *InvoiceRegistry) notifyExitHopHtlcLocked( |
1051 | 1092 |
|
1052 | 1093 | var invoiceToExpire invoiceExpiry |
1053 | 1094 |
|
| 1095 | + log.Debugf("Settlement resolution: %T %v", resolution, resolution) |
| 1096 | + |
1054 | 1097 | switch res := resolution.(type) { |
1055 | 1098 | case *HtlcFailResolution: |
1056 | 1099 | // Inspect latest htlc state on the invoice. If it is found, |
@@ -1099,6 +1142,8 @@ func (i *InvoiceRegistry) notifyExitHopHtlcLocked( |
1099 | 1142 | // with our peer. |
1100 | 1143 | setID := ctx.setID() |
1101 | 1144 | settledHtlcSet := invoice.HTLCSet(setID, HtlcStateSettled) |
| 1145 | + log.Debugf("Settled htlc set size: %d", len(settledHtlcSet)) |
| 1146 | + |
1102 | 1147 | for key, htlc := range settledHtlcSet { |
1103 | 1148 | preimage := res.Preimage |
1104 | 1149 | if htlc.AMP != nil && htlc.AMP.Preimage != nil { |
@@ -1183,7 +1228,7 @@ func (i *InvoiceRegistry) notifyExitHopHtlcLocked( |
1183 | 1228 | } |
1184 | 1229 |
|
1185 | 1230 | // Now that the links have been notified of any state changes to their |
1186 | | - // HTLCs, we'll go ahead and notify any clients wiaiting on the invoice |
| 1231 | + // HTLCs, we'll go ahead and notify any clients waiting on the invoice |
1187 | 1232 | // state changes. |
1188 | 1233 | if updateSubscribers { |
1189 | 1234 | // We'll add a setID onto the notification, but only if this is |
|
0 commit comments