@@ -1099,118 +1099,26 @@ func (s *Switch) parseFailedPayment(deobfuscator ErrorDecrypter,
10991099// updates back. This behaviour is achieved by creation of payment circuits.
11001100func (s * Switch ) handlePacketForward (packet * htlcPacket ) error {
11011101 switch htlc := packet .htlc .(type ) {
1102-
11031102 // Channel link forwarded us a new htlc, therefore we initiate the
11041103 // payment circuit within our internal state so we can properly forward
11051104 // the ultimate settle message back latter.
11061105 case * lnwire.UpdateAddHTLC :
11071106 return s .handlePacketAdd (packet , htlc )
11081107
1109- case * lnwire.UpdateFailHTLC , * lnwire.UpdateFulfillHTLC :
1110- // If the source of this packet has not been set, use the
1111- // circuit map to lookup the origin.
1112- circuit , err := s .closeCircuit (packet )
1113- if err != nil {
1114- return err
1115- }
1116-
1117- // closeCircuit returns a nil circuit when a settle packet returns an
1118- // ErrUnknownCircuit error upon the inner call to CloseCircuit.
1119- if circuit == nil {
1120- return nil
1121- }
1122-
1123- fail , isFail := htlc .(* lnwire.UpdateFailHTLC )
1124- if isFail && ! packet .hasSource {
1125- // HTLC resolutions and messages restored from disk
1126- // don't have the obfuscator set from the original htlc
1127- // add packet - set it here for use in blinded errors.
1128- packet .obfuscator = circuit .ErrorEncrypter
1129-
1130- switch {
1131- // No message to encrypt, locally sourced payment.
1132- case circuit .ErrorEncrypter == nil :
1133-
1134- // If this is a resolution message, then we'll need to
1135- // encrypt it as it's actually internally sourced.
1136- case packet .isResolution :
1137- var err error
1138- // TODO(roasbeef): don't need to pass actually?
1139- failure := & lnwire.FailPermanentChannelFailure {}
1140- fail .Reason , err = circuit .ErrorEncrypter .EncryptFirstHop (
1141- failure ,
1142- )
1143- if err != nil {
1144- err = fmt .Errorf ("unable to obfuscate " +
1145- "error: %v" , err )
1146- log .Error (err )
1147- }
1148-
1149- // Alternatively, if the remote party send us an
1150- // UpdateFailMalformedHTLC, then we'll need to convert
1151- // this into a proper well formatted onion error as
1152- // there's no HMAC currently.
1153- case packet .convertedError :
1154- log .Infof ("Converting malformed HTLC error " +
1155- "for circuit for Circuit(%x: " +
1156- "(%s, %d) <-> (%s, %d))" , packet .circuit .PaymentHash ,
1157- packet .incomingChanID , packet .incomingHTLCID ,
1158- packet .outgoingChanID , packet .outgoingHTLCID )
1159-
1160- fail .Reason = circuit .ErrorEncrypter .EncryptMalformedError (
1161- fail .Reason ,
1162- )
1163-
1164- default :
1165- // Otherwise, it's a forwarded error, so we'll perform a
1166- // wrapper encryption as normal.
1167- fail .Reason = circuit .ErrorEncrypter .IntermediateEncrypt (
1168- fail .Reason ,
1169- )
1170- }
1171- } else if ! isFail && circuit .Outgoing != nil {
1172- // If this is an HTLC settle, and it wasn't from a
1173- // locally initiated HTLC, then we'll log a forwarding
1174- // event so we can flush it to disk later.
1175- //
1176- // TODO(roasbeef): only do this once link actually
1177- // fully settles?
1178- localHTLC := packet .incomingChanID == hop .Source
1179- if ! localHTLC {
1180- log .Infof ("Forwarded HTLC(%x) of %v (fee: %v) " +
1181- "from IncomingChanID(%v) to OutgoingChanID(%v)" ,
1182- circuit .PaymentHash [:], circuit .OutgoingAmount ,
1183- circuit .IncomingAmount - circuit .OutgoingAmount ,
1184- circuit .Incoming .ChanID , circuit .Outgoing .ChanID )
1185- s .fwdEventMtx .Lock ()
1186- s .pendingFwdingEvents = append (
1187- s .pendingFwdingEvents ,
1188- channeldb.ForwardingEvent {
1189- Timestamp : time .Now (),
1190- IncomingChanID : circuit .Incoming .ChanID ,
1191- OutgoingChanID : circuit .Outgoing .ChanID ,
1192- AmtIn : circuit .IncomingAmount ,
1193- AmtOut : circuit .OutgoingAmount ,
1194- },
1195- )
1196- s .fwdEventMtx .Unlock ()
1197- }
1198- }
1199-
1200- // A blank IncomingChanID in a circuit indicates that it is a pending
1201- // user-initiated payment.
1202- if packet .incomingChanID == hop .Source {
1203- s .wg .Add (1 )
1204- go s .handleLocalResponse (packet )
1205- return nil
1206- }
1108+ case * lnwire.UpdateFulfillHTLC :
1109+ return s .handlePacketSettle (packet )
12071110
1208- // Check to see that the source link is online before removing
1209- // the circuit.
1210- return s .mailOrchestrator .Deliver (packet .incomingChanID , packet )
1111+ // Channel link forwarded us an update_fail_htlc message.
1112+ //
1113+ // NOTE: when the channel link receives an update_fail_malformed_htlc
1114+ // from upstream, it will convert the message into update_fail_htlc and
1115+ // forward it. Thus there's no need to catch `UpdateFailMalformedHTLC`
1116+ // here.
1117+ case * lnwire.UpdateFailHTLC :
1118+ return s .handlePacketFail (packet , htlc )
12111119
12121120 default :
1213- return errors . New ("wrong update type" )
1121+ return fmt . Errorf ("wrong update type: %T" , htlc )
12141122 }
12151123}
12161124
@@ -3051,3 +2959,161 @@ func (s *Switch) handlePacketAdd(packet *htlcPacket,
30512959
30522960 return destination .handleSwitchPacket (packet )
30532961}
2962+
2963+ // handlePacketSettle handles forwarding a settle packet.
2964+ func (s * Switch ) handlePacketSettle (packet * htlcPacket ) error {
2965+ // If the source of this packet has not been set, use the circuit map
2966+ // to lookup the origin.
2967+ circuit , err := s .closeCircuit (packet )
2968+ if err != nil {
2969+ return err
2970+ }
2971+
2972+ // closeCircuit returns a nil circuit when a settle packet returns an
2973+ // ErrUnknownCircuit error upon the inner call to CloseCircuit.
2974+ //
2975+ // NOTE: We can only get a nil circuit when it has already been deleted
2976+ // and when `UpdateFulfillHTLC` is received. After which `RevokeAndAck`
2977+ // is received, which invokes `processRemoteSettleFails` in its link.
2978+ if circuit == nil {
2979+ log .Debugf ("Found nil circuit: packet=%v" , spew .Sdump (packet ))
2980+ return nil
2981+ }
2982+
2983+ localHTLC := packet .incomingChanID == hop .Source
2984+
2985+ // If this is a locally initiated HTLC, we need to handle the packet by
2986+ // storing the network result.
2987+ //
2988+ // A blank IncomingChanID in a circuit indicates that it is a pending
2989+ // user-initiated payment.
2990+ //
2991+ // NOTE: `closeCircuit` modifies the state of `packet`.
2992+ if localHTLC {
2993+ // TODO(yy): remove the goroutine and send back the error here.
2994+ s .wg .Add (1 )
2995+ go s .handleLocalResponse (packet )
2996+
2997+ // If this is a locally initiated HTLC, there's no need to
2998+ // forward it so we exit.
2999+ return nil
3000+ }
3001+
3002+ // If this is an HTLC settle, and it wasn't from a locally initiated
3003+ // HTLC, then we'll log a forwarding event so we can flush it to disk
3004+ // later.
3005+ if circuit .Outgoing != nil {
3006+ log .Infof ("Forwarded HTLC(%x) of %v (fee: %v) " +
3007+ "from IncomingChanID(%v) to OutgoingChanID(%v)" ,
3008+ circuit .PaymentHash [:], circuit .OutgoingAmount ,
3009+ circuit .IncomingAmount - circuit .OutgoingAmount ,
3010+ circuit .Incoming .ChanID , circuit .Outgoing .ChanID )
3011+
3012+ s .fwdEventMtx .Lock ()
3013+ s .pendingFwdingEvents = append (
3014+ s .pendingFwdingEvents ,
3015+ channeldb.ForwardingEvent {
3016+ Timestamp : time .Now (),
3017+ IncomingChanID : circuit .Incoming .ChanID ,
3018+ OutgoingChanID : circuit .Outgoing .ChanID ,
3019+ AmtIn : circuit .IncomingAmount ,
3020+ AmtOut : circuit .OutgoingAmount ,
3021+ },
3022+ )
3023+ s .fwdEventMtx .Unlock ()
3024+ }
3025+
3026+ // Deliver this packet.
3027+ return s .mailOrchestrator .Deliver (packet .incomingChanID , packet )
3028+ }
3029+
3030+ // handlePacketFail handles forwarding a fail packet.
3031+ func (s * Switch ) handlePacketFail (packet * htlcPacket ,
3032+ htlc * lnwire.UpdateFailHTLC ) error {
3033+
3034+ // If the source of this packet has not been set, use the circuit map
3035+ // to lookup the origin.
3036+ circuit , err := s .closeCircuit (packet )
3037+ if err != nil {
3038+ return err
3039+ }
3040+
3041+ // If this is a locally initiated HTLC, we need to handle the packet by
3042+ // storing the network result.
3043+ //
3044+ // A blank IncomingChanID in a circuit indicates that it is a pending
3045+ // user-initiated payment.
3046+ //
3047+ // NOTE: `closeCircuit` modifies the state of `packet`.
3048+ if packet .incomingChanID == hop .Source {
3049+ // TODO(yy): remove the goroutine and send back the error here.
3050+ s .wg .Add (1 )
3051+ go s .handleLocalResponse (packet )
3052+
3053+ // If this is a locally initiated HTLC, there's no need to
3054+ // forward it so we exit.
3055+ return nil
3056+ }
3057+
3058+ // Exit early if this hasSource is true. This flag is only set via
3059+ // mailbox's `FailAdd`. This method has two callsites,
3060+ // - the packet has timed out after `MailboxDeliveryTimeout`, defaults
3061+ // to 1 min.
3062+ // - the HTLC fails the validation in `channel.AddHTLC`.
3063+ // In either case, the `Reason` field is populated. Thus there's no
3064+ // need to proceed and extract the failure reason below.
3065+ if packet .hasSource {
3066+ // Deliver this packet.
3067+ return s .mailOrchestrator .Deliver (packet .incomingChanID , packet )
3068+ }
3069+
3070+ // HTLC resolutions and messages restored from disk don't have the
3071+ // obfuscator set from the original htlc add packet - set it here for
3072+ // use in blinded errors.
3073+ packet .obfuscator = circuit .ErrorEncrypter
3074+
3075+ switch {
3076+ // No message to encrypt, locally sourced payment.
3077+ case circuit .ErrorEncrypter == nil :
3078+ // TODO(yy) further check this case as we shouldn't end up here
3079+ // as `isLocal` is already false.
3080+
3081+ // If this is a resolution message, then we'll need to encrypt it as
3082+ // it's actually internally sourced.
3083+ case packet .isResolution :
3084+ var err error
3085+ // TODO(roasbeef): don't need to pass actually?
3086+ failure := & lnwire.FailPermanentChannelFailure {}
3087+ htlc .Reason , err = circuit .ErrorEncrypter .EncryptFirstHop (
3088+ failure ,
3089+ )
3090+ if err != nil {
3091+ err = fmt .Errorf ("unable to obfuscate error: %w" , err )
3092+ log .Error (err )
3093+ }
3094+
3095+ // Alternatively, if the remote party sends us an
3096+ // UpdateFailMalformedHTLC, then we'll need to convert this into a
3097+ // proper well formatted onion error as there's no HMAC currently.
3098+ case packet .convertedError :
3099+ log .Infof ("Converting malformed HTLC error for circuit for " +
3100+ "Circuit(%x: (%s, %d) <-> (%s, %d))" ,
3101+ packet .circuit .PaymentHash ,
3102+ packet .incomingChanID , packet .incomingHTLCID ,
3103+ packet .outgoingChanID , packet .outgoingHTLCID )
3104+
3105+ htlc .Reason = circuit .ErrorEncrypter .EncryptMalformedError (
3106+ htlc .Reason ,
3107+ )
3108+
3109+ default :
3110+ // Otherwise, it's a forwarded error, so we'll perform a
3111+ // wrapper encryption as normal.
3112+ htlc .Reason = circuit .ErrorEncrypter .IntermediateEncrypt (
3113+ htlc .Reason ,
3114+ )
3115+ }
3116+
3117+ // Deliver this packet.
3118+ return s .mailOrchestrator .Deliver (packet .incomingChanID , packet )
3119+ }
0 commit comments