@@ -958,7 +958,7 @@ func (l *channelLink) resolveFwdPkgs() error {
958958
959959 // If any of our reprocessing steps require an update to the commitment
960960 // txn, we initiate a state transition to capture all relevant changes.
961- if l .channel .PendingLocalUpdateCount ( ) > 0 {
961+ if l .channel .NumPendingUpdates ( lntypes . Local , lntypes . Remote ) > 0 {
962962 return l .updateCommitTx ()
963963 }
964964
@@ -1086,6 +1086,83 @@ func (l *channelLink) loadAndRemove() error {
10861086 return l .channel .RemoveFwdPkgs (removeHeights ... )
10871087}
10881088
1089+ // handleChanSyncErr performs the error handling logic in the case where we
1090+ // could not successfully syncChanStates with our channel peer.
1091+ func (l * channelLink ) handleChanSyncErr (err error ) {
1092+ l .log .Warnf ("error when syncing channel states: %v" , err )
1093+
1094+ var errDataLoss * lnwallet.ErrCommitSyncLocalDataLoss
1095+
1096+ switch {
1097+ case errors .Is (err , ErrLinkShuttingDown ):
1098+ l .log .Debugf ("unable to sync channel states, link is " +
1099+ "shutting down" )
1100+ return
1101+
1102+ // We failed syncing the commit chains, probably because the remote has
1103+ // lost state. We should force close the channel.
1104+ case errors .Is (err , lnwallet .ErrCommitSyncRemoteDataLoss ):
1105+ fallthrough
1106+
1107+ // The remote sent us an invalid last commit secret, we should force
1108+ // close the channel.
1109+ // TODO(halseth): and permanently ban the peer?
1110+ case errors .Is (err , lnwallet .ErrInvalidLastCommitSecret ):
1111+ fallthrough
1112+
1113+ // The remote sent us a commit point different from what they sent us
1114+ // before.
1115+ // TODO(halseth): ban peer?
1116+ case errors .Is (err , lnwallet .ErrInvalidLocalUnrevokedCommitPoint ):
1117+ // We'll fail the link and tell the peer to force close the
1118+ // channel. Note that the database state is not updated here,
1119+ // but will be updated when the close transaction is ready to
1120+ // avoid that we go down before storing the transaction in the
1121+ // db.
1122+ l .failf (
1123+ LinkFailureError {
1124+ code : ErrSyncError ,
1125+ FailureAction : LinkFailureForceClose ,
1126+ },
1127+ "unable to synchronize channel states: %v" , err ,
1128+ )
1129+
1130+ // We have lost state and cannot safely force close the channel. Fail
1131+ // the channel and wait for the remote to hopefully force close it. The
1132+ // remote has sent us its latest unrevoked commitment point, and we'll
1133+ // store it in the database, such that we can attempt to recover the
1134+ // funds if the remote force closes the channel.
1135+ case errors .As (err , & errDataLoss ):
1136+ err := l .channel .MarkDataLoss (
1137+ errDataLoss .CommitPoint ,
1138+ )
1139+ if err != nil {
1140+ l .log .Errorf ("unable to mark channel data loss: %v" ,
1141+ err )
1142+ }
1143+
1144+ // We determined the commit chains were not possible to sync. We
1145+ // cautiously fail the channel, but don't force close.
1146+ // TODO(halseth): can we safely force close in any cases where this
1147+ // error is returned?
1148+ case errors .Is (err , lnwallet .ErrCannotSyncCommitChains ):
1149+ if err := l .channel .MarkBorked (); err != nil {
1150+ l .log .Errorf ("unable to mark channel borked: %v" , err )
1151+ }
1152+
1153+ // Other, unspecified error.
1154+ default :
1155+ }
1156+
1157+ l .failf (
1158+ LinkFailureError {
1159+ code : ErrRecoveryError ,
1160+ FailureAction : LinkFailureForceNone ,
1161+ },
1162+ "unable to synchronize channel states: %v" , err ,
1163+ )
1164+ }
1165+
10891166// htlcManager is the primary goroutine which drives a channel's commitment
10901167// update state-machine in response to messages received via several channels.
10911168// This goroutine reads messages from the upstream (remote) peer, and also from
@@ -1121,89 +1198,7 @@ func (l *channelLink) htlcManager() {
11211198 if l .cfg .SyncStates {
11221199 err := l .syncChanStates ()
11231200 if err != nil {
1124- l .log .Warnf ("error when syncing channel states: %v" , err )
1125-
1126- errDataLoss , localDataLoss :=
1127- err .(* lnwallet.ErrCommitSyncLocalDataLoss )
1128-
1129- switch {
1130- case err == ErrLinkShuttingDown :
1131- l .log .Debugf ("unable to sync channel states, " +
1132- "link is shutting down" )
1133- return
1134-
1135- // We failed syncing the commit chains, probably
1136- // because the remote has lost state. We should force
1137- // close the channel.
1138- case err == lnwallet .ErrCommitSyncRemoteDataLoss :
1139- fallthrough
1140-
1141- // The remote sent us an invalid last commit secret, we
1142- // should force close the channel.
1143- // TODO(halseth): and permanently ban the peer?
1144- case err == lnwallet .ErrInvalidLastCommitSecret :
1145- fallthrough
1146-
1147- // The remote sent us a commit point different from
1148- // what they sent us before.
1149- // TODO(halseth): ban peer?
1150- case err == lnwallet .ErrInvalidLocalUnrevokedCommitPoint :
1151- // We'll fail the link and tell the peer to
1152- // force close the channel. Note that the
1153- // database state is not updated here, but will
1154- // be updated when the close transaction is
1155- // ready to avoid that we go down before
1156- // storing the transaction in the db.
1157- l .failf (
1158- //nolint:lll
1159- LinkFailureError {
1160- code : ErrSyncError ,
1161- FailureAction : LinkFailureForceClose ,
1162- },
1163- "unable to synchronize channel " +
1164- "states: %v" , err ,
1165- )
1166- return
1167-
1168- // We have lost state and cannot safely force close the
1169- // channel. Fail the channel and wait for the remote to
1170- // hopefully force close it. The remote has sent us its
1171- // latest unrevoked commitment point, and we'll store
1172- // it in the database, such that we can attempt to
1173- // recover the funds if the remote force closes the
1174- // channel.
1175- case localDataLoss :
1176- err := l .channel .MarkDataLoss (
1177- errDataLoss .CommitPoint ,
1178- )
1179- if err != nil {
1180- l .log .Errorf ("unable to mark channel " +
1181- "data loss: %v" , err )
1182- }
1183-
1184- // We determined the commit chains were not possible to
1185- // sync. We cautiously fail the channel, but don't
1186- // force close.
1187- // TODO(halseth): can we safely force close in any
1188- // cases where this error is returned?
1189- case err == lnwallet .ErrCannotSyncCommitChains :
1190- if err := l .channel .MarkBorked (); err != nil {
1191- l .log .Errorf ("unable to mark channel " +
1192- "borked: %v" , err )
1193- }
1194-
1195- // Other, unspecified error.
1196- default :
1197- }
1198-
1199- l .failf (
1200- LinkFailureError {
1201- code : ErrRecoveryError ,
1202- FailureAction : LinkFailureForceNone ,
1203- },
1204- "unable to synchronize channel " +
1205- "states: %v" , err ,
1206- )
1201+ l .handleChanSyncErr (err )
12071202 return
12081203 }
12091204 }
@@ -1291,15 +1286,19 @@ func (l *channelLink) htlcManager() {
12911286 // the batch ticker so that it can be cleared. Otherwise pause
12921287 // the ticker to prevent waking up the htlcManager while the
12931288 // batch is empty.
1294- if l .channel .PendingLocalUpdateCount () > 0 {
1289+ numUpdates := l .channel .NumPendingUpdates (
1290+ lntypes .Local , lntypes .Remote ,
1291+ )
1292+ if numUpdates > 0 {
12951293 l .cfg .BatchTicker .Resume ()
12961294 l .log .Tracef ("BatchTicker resumed, " +
1297- "PendingLocalUpdateCount=%d" ,
1298- l .channel .PendingLocalUpdateCount ())
1295+ "NumPendingUpdates(Local, Remote)=%d" ,
1296+ numUpdates ,
1297+ )
12991298 } else {
13001299 l .cfg .BatchTicker .Pause ()
13011300 l .log .Trace ("BatchTicker paused due to zero " +
1302- "PendingLocalUpdateCount " )
1301+ "NumPendingUpdates(Local, Remote) " )
13031302 }
13041303
13051304 select {
@@ -1657,7 +1656,7 @@ func (l *channelLink) handleDownstreamUpdateAdd(pkt *htlcPacket) error {
16571656 l .log .Tracef ("received downstream htlc: payment_hash=%x, " +
16581657 "local_log_index=%v, pend_updates=%v" ,
16591658 htlc .PaymentHash [:], index ,
1660- l .channel .PendingLocalUpdateCount ( ))
1659+ l .channel .NumPendingUpdates ( lntypes . Local , lntypes . Remote ))
16611660
16621661 pkt .outgoingChanID = l .ShortChanID ()
16631662 pkt .outgoingHTLCID = index
@@ -1863,7 +1862,8 @@ func (l *channelLink) handleDownstreamPkt(pkt *htlcPacket) {
18631862// tryBatchUpdateCommitTx updates the commitment transaction if the batch is
18641863// full.
18651864func (l * channelLink ) tryBatchUpdateCommitTx () {
1866- if l .channel .PendingLocalUpdateCount () < uint64 (l .cfg .BatchSize ) {
1865+ pending := l .channel .NumPendingUpdates (lntypes .Local , lntypes .Remote )
1866+ if pending < uint64 (l .cfg .BatchSize ) {
18671867 return
18681868 }
18691869
@@ -1939,7 +1939,6 @@ func (l *channelLink) cleanupSpuriousResponse(pkt *htlcPacket) {
19391939// direct channel with, updating our respective commitment chains.
19401940func (l * channelLink ) handleUpstreamMsg (msg lnwire.Message ) {
19411941 switch msg := msg .(type ) {
1942-
19431942 case * lnwire.UpdateAddHTLC :
19441943 if l .IsFlushing (Incoming ) {
19451944 // This is forbidden by the protocol specification.
@@ -2597,9 +2596,9 @@ func (l *channelLink) updateCommitTx() error {
25972596 l .cfg .PendingCommitTicker .Resume ()
25982597 l .log .Trace ("PendingCommitTicker resumed" )
25992598
2599+ n := l .channel .NumPendingUpdates (lntypes .Local , lntypes .Remote )
26002600 l .log .Tracef ("revocation window exhausted, unable to send: " +
2601- "%v, pend_updates=%v, dangling_closes%v" ,
2602- l .channel .PendingLocalUpdateCount (),
2601+ "%v, pend_updates=%v, dangling_closes%v" , n ,
26032602 lnutils .SpewLogClosure (l .openedCircuits ),
26042603 lnutils .SpewLogClosure (l .closedCircuits ))
26052604
0 commit comments