From 87b490dfc4e817973450a3659b2042dcedc6029b Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Mon, 30 Jun 2025 21:48:52 +0800 Subject: [PATCH] htlcswitch: add `processRemoteError` and `processRemoteUpdateFee` --- htlcswitch/link.go | 116 ++++++++++++++++++++++++++------------------- 1 file changed, 66 insertions(+), 50 deletions(-) diff --git a/htlcswitch/link.go b/htlcswitch/link.go index 2cbcfa0bf..759095847 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -1903,8 +1903,6 @@ func (l *channelLink) cleanupSpuriousResponse(pkt *htlcPacket) { // handleUpstreamMsg processes wire messages related to commitment state // updates from the upstream peer. The upstream peer is the peer whom we have a // direct channel with, updating our respective commitment chains. -// -//nolint:funlen func (l *channelLink) handleUpstreamMsg(ctx context.Context, msg lnwire.Message) { @@ -1968,41 +1966,14 @@ func (l *channelLink) handleUpstreamMsg(ctx context.Context, } case *lnwire.UpdateFee: - // Check and see if their proposed fee-rate would make us - // exceed the fee threshold. - fee := chainfee.SatPerKWeight(msg.FeePerKw) - - isDust, err := l.exceedsFeeExposureLimit(fee) + err := l.processRemoteUpdateFee(msg) if err != nil { - // This shouldn't typically happen. If it does, it - // indicates something is wrong with our channel state. - l.log.Errorf("Unable to determine if fee threshold " + - "exceeded") - l.failf(LinkFailureError{code: ErrInternalError}, - "error calculating fee exposure: %v", err) + l.log.Errorf("failed to process remote update fee: %v", + err) return } - if isDust { - // The proposed fee-rate makes us exceed the fee - // threshold. - l.failf(LinkFailureError{code: ErrInternalError}, - "fee threshold exceeded: %v", err) - return - } - - // We received fee update from peer. If we are the initiator we - // will fail the channel, if not we will apply the update. - if err := l.channel.ReceiveUpdateFee(fee); err != nil { - l.failf(LinkFailureError{code: ErrInvalidUpdate}, - "error receiving fee update: %v", err) - return - } - - // Update the mailbox's feerate as well. - l.mailBox.SetFeeRate(fee) - case *lnwire.Stfu: err := l.handleStfu(msg) if err != nil { @@ -2017,28 +1988,11 @@ func (l *channelLink) handleUpstreamMsg(ctx context.Context, msg.Warning()) case *lnwire.Error: - // Error received from remote, MUST fail channel, but should - // only print the contents of the error message if all - // characters are printable ASCII. - l.failf( - LinkFailureError{ - code: ErrRemoteError, + l.processRemoteError(msg) - // TODO(halseth): we currently don't fail the - // channel permanently, as there are some sync - // issues with other implementations that will - // lead to them sending an error message, but - // we can recover from on next connection. See - // https://github.com/ElementsProject/lightning/issues/4212 - PermanentFailure: false, - }, - "ChannelPoint(%v): received error from peer: %v", - l.channel.ChannelPoint(), msg.Error(), - ) default: l.log.Warnf("received unknown message of type %T", msg) } - } // handleStfu implements the top-level logic for handling the Stfu message from @@ -4711,3 +4665,65 @@ func (l *channelLink) processRemoteRevokeAndAck(ctx context.Context, return nil } + +// processRemoteUpdateFee takes an `UpdateFee` msg sent from the remote and +// processes it. +func (l *channelLink) processRemoteUpdateFee(msg *lnwire.UpdateFee) error { + // Check and see if their proposed fee-rate would make us exceed the fee + // threshold. + fee := chainfee.SatPerKWeight(msg.FeePerKw) + + isDust, err := l.exceedsFeeExposureLimit(fee) + if err != nil { + // This shouldn't typically happen. If it does, it indicates + // something is wrong with our channel state. + l.log.Errorf("Unable to determine if fee threshold " + + "exceeded") + l.failf(LinkFailureError{code: ErrInternalError}, + "error calculating fee exposure: %v", err) + + return err + } + + if isDust { + // The proposed fee-rate makes us exceed the fee threshold. + l.failf(LinkFailureError{code: ErrInternalError}, + "fee threshold exceeded: %v", err) + return err + } + + // We received fee update from peer. If we are the initiator we will + // fail the channel, if not we will apply the update. + if err := l.channel.ReceiveUpdateFee(fee); err != nil { + l.failf(LinkFailureError{code: ErrInvalidUpdate}, + "error receiving fee update: %v", err) + return err + } + + // Update the mailbox's feerate as well. + l.mailBox.SetFeeRate(fee) + + return nil +} + +// processRemoteError takes an `Error` msg sent from the remote and fails the +// channel link. +func (l *channelLink) processRemoteError(msg *lnwire.Error) { + // Error received from remote, MUST fail channel, but should only print + // the contents of the error message if all characters are printable + // ASCII. + l.failf( + // TODO(halseth): we currently don't fail the channel + // permanently, as there are some sync issues with other + // implementations that will lead to them sending an + // error message, but we can recover from on next + // connection. See + // https://github.com/ElementsProject/lightning/issues/4212 + LinkFailureError{ + code: ErrRemoteError, + PermanentFailure: false, + }, + "ChannelPoint(%v): received error from peer: %v", + l.channel.ChannelPoint(), msg.Error(), + ) +}