@@ -74,6 +74,11 @@ type RegistryConfig struct {
7474 // KeysendHoldTime indicates for how long we want to accept and hold
7575 // spontaneous keysend payments.
7676 KeysendHoldTime time.Duration
77+
78+ // HtlcModifier is a service that intercepts invoice HTLCs during the
79+ // settlement phase, enabling a subscribed client to modify certain
80+ // aspects of those HTLCs.
81+ HtlcModifier HtlcModifier
7782}
7883
7984// htlcReleaseEvent describes an htlc auto-release event. It is used to release
@@ -887,6 +892,7 @@ func (i *InvoiceRegistry) processAMP(ctx invoiceUpdateCtx) error {
887892func (i * InvoiceRegistry ) NotifyExitHopHtlc (rHash lntypes.Hash ,
888893 amtPaid lnwire.MilliSatoshi , expiry uint32 , currentHeight int32 ,
889894 circuitKey CircuitKey , hodlChan chan <- interface {},
895+ wireCustomRecords lnwire.CustomRecords ,
890896 payload Payload ) (HtlcResolution , error ) {
891897
892898 // Create the update context containing the relevant details of the
@@ -898,6 +904,7 @@ func (i *InvoiceRegistry) NotifyExitHopHtlc(rHash lntypes.Hash,
898904 expiry : expiry ,
899905 currentHeight : currentHeight ,
900906 finalCltvRejectDelta : i .cfg .FinalCltvRejectDelta ,
907+ wireCustomRecords : wireCustomRecords ,
901908 customRecords : payload .CustomRecords (),
902909 mpp : payload .MultiPath (),
903910 amp : payload .AMPRecord (),
@@ -998,6 +1005,54 @@ func (i *InvoiceRegistry) notifyExitHopHtlcLocked(
9981005 )
9991006
10001007 callback := func (inv * Invoice ) (* InvoiceUpdateDesc , error ) {
1008+ // Provide the invoice to the settlement interceptor to allow
1009+ // the interceptor's client an opportunity to manipulate the
1010+ // settlement process.
1011+ clientReq := HtlcModifyRequest {
1012+ WireCustomRecords : ctx .wireCustomRecords ,
1013+ ExitHtlcCircuitKey : ctx .circuitKey ,
1014+ ExitHtlcAmt : ctx .amtPaid ,
1015+ ExitHtlcExpiry : ctx .expiry ,
1016+ CurrentHeight : uint32 (ctx .currentHeight ),
1017+ Invoice : * inv ,
1018+ }
1019+ interceptSession := i .cfg .HtlcModifier .Intercept (
1020+ 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+ var interceptErr error
1027+ interceptSession .WhenSome (func (session InterceptSession ) {
1028+ log .Debug ("Waiting for client response from invoice " +
1029+ "HTLC interceptor session" )
1030+
1031+ select {
1032+ case resp := <- session .ClientResponseChannel :
1033+ log .Debugf ("Received invoice HTLC interceptor " +
1034+ "response: %v" , resp )
1035+
1036+ if resp .AmountPaid != 0 {
1037+ ctx .amtPaid = resp .AmountPaid
1038+ }
1039+
1040+ case err := <- session .ClientErrChannel :
1041+ log .Errorf ("Error from invoice HTLC " +
1042+ "interceptor session: %v" , err )
1043+
1044+ interceptErr = err
1045+
1046+ case <- session .Quit :
1047+ // At this point, the interceptor session has
1048+ // quit.
1049+ }
1050+ })
1051+ if interceptErr != nil {
1052+ return nil , fmt .Errorf ("error during invoice HTLC " +
1053+ "interception: %w" , interceptErr )
1054+ }
1055+
10011056 updateDesc , res , err := updateInvoice (ctx , inv )
10021057 if err != nil {
10031058 return nil , err
@@ -1051,6 +1106,8 @@ func (i *InvoiceRegistry) notifyExitHopHtlcLocked(
10511106
10521107 var invoiceToExpire invoiceExpiry
10531108
1109+ log .Tracef ("Settlement resolution: %T %v" , resolution , resolution )
1110+
10541111 switch res := resolution .(type ) {
10551112 case * HtlcFailResolution :
10561113 // Inspect latest htlc state on the invoice. If it is found,
@@ -1183,7 +1240,7 @@ func (i *InvoiceRegistry) notifyExitHopHtlcLocked(
11831240 }
11841241
11851242 // 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
1243+ // HTLCs, we'll go ahead and notify any clients waiting on the invoice
11871244 // state changes.
11881245 if updateSubscribers {
11891246 // We'll add a setID onto the notification, but only if this is
0 commit comments