lnpeer.reestablish_chan: enforce order of replaying commitsig/revack
When replaying messages during channel-reestablishment,
previously we first resent all update messages, along with potential commitment_signed messages,
and then we potentially resent a single revoke_and_ack.
This can result in incorrect behaviour in case both a commitment_signed and a revoke_and_ack needs to be resent.
When replaying messages, the relative order of commitment_signed and revoke_and_messages needs to be preserved.
(the order of updates (htlc/fee) in relation to the revack messages does not matter)
implements https://github.com/lightning/bolts/pull/810
The logic here is somewhat based on what c-lightning does:
01e5f1886e/channeld/channeld.c (L3059)
This commit is contained in:
@@ -28,6 +28,7 @@ class HTLCManager:
|
||||
log[LOCAL] = deepcopy(initial)
|
||||
log[REMOTE] = deepcopy(initial)
|
||||
log[LOCAL]['unacked_updates'] = {}
|
||||
log[LOCAL]['was_revoke_last'] = False
|
||||
|
||||
# maybe bootstrap fee_updates if initial_feerate was provided
|
||||
if initial_feerate is not None:
|
||||
@@ -155,6 +156,7 @@ class HTLCManager:
|
||||
def send_ctx(self) -> None:
|
||||
assert self.ctn_latest(REMOTE) == self.ctn_oldest_unrevoked(REMOTE), (self.ctn_latest(REMOTE), self.ctn_oldest_unrevoked(REMOTE))
|
||||
self._set_revack_pending(REMOTE, True)
|
||||
self.log[LOCAL]['was_revoke_last'] = False
|
||||
|
||||
@with_lock
|
||||
def recv_ctx(self) -> None:
|
||||
@@ -165,6 +167,7 @@ class HTLCManager:
|
||||
def send_rev(self) -> None:
|
||||
self.log[LOCAL]['ctn'] += 1
|
||||
self._set_revack_pending(LOCAL, False)
|
||||
self.log[LOCAL]['was_revoke_last'] = True
|
||||
# htlcs
|
||||
for htlc_id in self._maybe_active_htlc_ids[REMOTE]:
|
||||
ctns = self.log[REMOTE]['locked_in'][htlc_id]
|
||||
@@ -287,6 +290,11 @@ class HTLCManager:
|
||||
return {ctn: [bfh(msg) for msg in messages]
|
||||
for ctn, messages in self.log[LOCAL]['unacked_updates'].items()}
|
||||
|
||||
@with_lock
|
||||
def was_revoke_last(self) -> bool:
|
||||
"""Whether we sent a revoke_and_ack after the last commitment_signed we sent."""
|
||||
return self.log[LOCAL].get('was_revoke_last') or False
|
||||
|
||||
##### Queries re HTLCs:
|
||||
|
||||
def get_htlc_by_id(self, htlc_proposer: HTLCOwner, htlc_id: int) -> UpdateAddHtlc:
|
||||
|
||||
Reference in New Issue
Block a user