commit 940fc86749831265c8b4accd9d500b6b9ece2ce2
parent 107f271e583405ea6e3f4fbe7d72733b740a3b98
Author: SomberNight <somber.night@protonmail.com>
Date: Mon, 5 Aug 2019 17:43:06 +0200
lnpeer: reestablish_channel - fix data_loss_protect edge case
Diffstat:
3 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/electrum/lnchannel.py b/electrum/lnchannel.py
@@ -490,6 +490,7 @@ class Channel(Logger):
def get_secret_and_point(self, subject, ctn) -> Tuple[Optional[bytes], bytes]:
assert type(subject) is HTLCOwner
+ assert ctn >= 0, ctn
offset = ctn - self.get_oldest_unrevoked_ctn(subject)
if subject == REMOTE:
if offset > 1:
diff --git a/electrum/lnpeer.py b/electrum/lnpeer.py
@@ -743,6 +743,11 @@ class Peer(Logger):
their_oldest_unrevoked_remote_ctn = int.from_bytes(channel_reestablish_msg["next_remote_revocation_number"], 'big')
their_local_pcp = channel_reestablish_msg.get("my_current_per_commitment_point")
their_claim_of_our_last_per_commitment_secret = channel_reestablish_msg.get("your_last_per_commitment_secret")
+ # sanity checks of received values
+ if their_next_local_ctn < 0:
+ raise RemoteMisbehaving(f"channel reestablish: their_next_local_ctn < 0")
+ if their_oldest_unrevoked_remote_ctn < 0:
+ raise RemoteMisbehaving(f"channel reestablish: their_oldest_unrevoked_remote_ctn < 0")
should_close_we_are_ahead = False
should_close_they_are_ahead = False
@@ -788,7 +793,11 @@ class Peer(Logger):
if their_local_pcp is None or their_claim_of_our_last_per_commitment_secret is None:
# if DLP was enabled, absence of fields is not OK
return not dlp_enabled
- our_pcs, __ = chan.get_secret_and_point(LOCAL, their_oldest_unrevoked_remote_ctn - 1)
+ if their_oldest_unrevoked_remote_ctn > 0:
+ our_pcs, __ = chan.get_secret_and_point(LOCAL, their_oldest_unrevoked_remote_ctn - 1)
+ else:
+ assert their_oldest_unrevoked_remote_ctn == 0
+ our_pcs = bytes(32)
if our_pcs != their_claim_of_our_last_per_commitment_secret:
self.logger.error(f"channel_reestablish: (DLP) local PCS mismatch: {bh2u(our_pcs)} != {bh2u(their_claim_of_our_last_per_commitment_secret)}")
return False
diff --git a/electrum/lnutil.py b/electrum/lnutil.py
@@ -151,6 +151,7 @@ class RevocationStore:
self.index -= 1
def retrieve_secret(self, index: int) -> bytes:
+ assert index <= self.START_INDEX, index
for bucket in self.buckets:
if bucket is None:
raise UnableToDeriveSecret()