htlcswitch: add processRemoteError and processRemoteUpdateFee

This commit is contained in:
yyforyongyu
2025-06-30 21:48:52 +08:00
parent 4017104475
commit 87b490dfc4

View File

@@ -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(),
)
}