Browse Source

lnchannel: clean-up docstrings a bit

Removed lnd copyright as by now everything covered in this file
has been rewritten.
master
SomberNight 6 years ago
parent
commit
8ad6d5ddda
No known key found for this signature in database
GPG Key ID: B33B5F232C6271E9
  1. 93
      electrum/lnchannel.py
  2. 2
      electrum/lnutil.py
  3. 3
      electrum/tests/test_lnchannel.py

93
electrum/lnchannel.py

@ -1,5 +1,4 @@
# Copyright (C) 2018 The Electrum developers # Copyright (C) 2018 The Electrum developers
# Copyright (C) 2015-2018 The Lightning Network Developers
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal # of this software and associated documentation files (the "Software"), to deal
@ -19,9 +18,6 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE. # THE SOFTWARE.
# API (method signatures and docstrings) partially copied from lnd
# 42de4400bff5105352d0552155f73589166d162b
import os import os
from collections import namedtuple, defaultdict from collections import namedtuple, defaultdict
import binascii import binascii
@ -499,11 +495,8 @@ class Channel(Logger):
return redeem_script_to_address('p2wsh', script) return redeem_script_to_address('p2wsh', script)
def add_htlc(self, htlc: UpdateAddHtlc) -> UpdateAddHtlc: def add_htlc(self, htlc: UpdateAddHtlc) -> UpdateAddHtlc:
""" """Adds a new LOCAL HTLC to the channel.
AddHTLC adds an HTLC to the state machine's local update log. This method Action must be initiated by LOCAL.
should be called when preparing to send an outgoing HTLC.
This docstring is from LND.
""" """
if isinstance(htlc, dict): # legacy conversion # FIXME remove if isinstance(htlc, dict): # legacy conversion # FIXME remove
htlc = UpdateAddHtlc(**htlc) htlc = UpdateAddHtlc(**htlc)
@ -517,12 +510,8 @@ class Channel(Logger):
return htlc return htlc
def receive_htlc(self, htlc: UpdateAddHtlc, onion_packet:bytes = None) -> UpdateAddHtlc: def receive_htlc(self, htlc: UpdateAddHtlc, onion_packet:bytes = None) -> UpdateAddHtlc:
""" """Adds a new REMOTE HTLC to the channel.
ReceiveHTLC adds an HTLC to the state machine's remote update log. This Action must be initiated by REMOTE.
method should be called in response to receiving a new HTLC from the remote
party.
This docstring is from LND.
""" """
if isinstance(htlc, dict): # legacy conversion # FIXME remove if isinstance(htlc, dict): # legacy conversion # FIXME remove
htlc = UpdateAddHtlc(**htlc) htlc = UpdateAddHtlc(**htlc)
@ -543,17 +532,10 @@ class Channel(Logger):
self.logger.info("receive_htlc") self.logger.info("receive_htlc")
return htlc return htlc
def sign_next_commitment(self): def sign_next_commitment(self) -> Tuple[bytes, Sequence[bytes]]:
""" """Returns signatures for our next remote commitment tx.
SignNextCommitment signs a new commitment which includes any previous Action must be initiated by LOCAL.
unsettled HTLCs, any new HTLCs, and any modifications to prior HTLCs Finally, the next remote ctx becomes the latest remote ctx.
committed in previous commitment updates.
The first return parameter is the signature for the commitment transaction
itself, while the second parameter is are all HTLC signatures concatenated.
any). The HTLC signatures are sorted according to the BIP 69 order of the
HTLC's on the commitment transaction.
This docstring was adapted from LND.
""" """
next_remote_ctn = self.get_next_ctn(REMOTE) next_remote_ctn = self.get_next_ctn(REMOTE)
self.logger.info(f"sign_next_commitment {next_remote_ctn}") self.logger.info(f"sign_next_commitment {next_remote_ctn}")
@ -589,18 +571,10 @@ class Channel(Logger):
self.hm.send_ctx() self.hm.send_ctx()
return sig_64, htlcsigs return sig_64, htlcsigs
def receive_new_commitment(self, sig, htlc_sigs): def receive_new_commitment(self, sig: bytes, htlc_sigs: Sequence[bytes]) -> None:
""" """Processes signatures for our next local commitment tx, sent by the REMOTE.
ReceiveNewCommitment process a signature for a new commitment state sent by Action must be initiated by REMOTE.
the remote party. This method should be called in response to the If all checks pass, the next local ctx becomes the latest local ctx.
remote party initiating a new change, or when the remote party sends a
signature fully accepting a new state we've initiated. If we are able to
successfully validate the signature, then the generated commitment is added
to our local commitment chain. Once we send a revocation for our prior
state, then this newly added commitment becomes our current accepted channel
state.
This docstring is from LND.
""" """
# TODO in many failure cases below, we should "fail" the channel (force-close) # TODO in many failure cases below, we should "fail" the channel (force-close)
next_local_ctn = self.get_next_ctn(LOCAL) next_local_ctn = self.get_next_ctn(LOCAL)
@ -627,19 +601,19 @@ class Channel(Logger):
raise Exception(f'htlc sigs failure. recv {len(htlc_sigs)} sigs, expected {len(htlc_to_ctx_output_idx_map)}') raise Exception(f'htlc sigs failure. recv {len(htlc_sigs)} sigs, expected {len(htlc_to_ctx_output_idx_map)}')
for (direction, htlc), (ctx_output_idx, htlc_relative_idx) in htlc_to_ctx_output_idx_map.items(): for (direction, htlc), (ctx_output_idx, htlc_relative_idx) in htlc_to_ctx_output_idx_map.items():
htlc_sig = htlc_sigs[htlc_relative_idx] htlc_sig = htlc_sigs[htlc_relative_idx]
self.verify_htlc(htlc=htlc, self._verify_htlc_sig(htlc=htlc,
htlc_sig=htlc_sig, htlc_sig=htlc_sig,
htlc_direction=direction, htlc_direction=direction,
pcp=pcp, pcp=pcp,
ctx=pending_local_commitment, ctx=pending_local_commitment,
ctx_output_idx=ctx_output_idx) ctx_output_idx=ctx_output_idx)
with self.db_lock: with self.db_lock:
self.hm.recv_ctx() self.hm.recv_ctx()
self.config[LOCAL].current_commitment_signature=sig self.config[LOCAL].current_commitment_signature=sig
self.config[LOCAL].current_htlc_signatures=htlc_sigs_string self.config[LOCAL].current_htlc_signatures=htlc_sigs_string
def verify_htlc(self, *, htlc: UpdateAddHtlc, htlc_sig: bytes, htlc_direction: Direction, def _verify_htlc_sig(self, *, htlc: UpdateAddHtlc, htlc_sig: bytes, htlc_direction: Direction,
pcp: bytes, ctx: Transaction, ctx_output_idx: int) -> None: pcp: bytes, ctx: Transaction, ctx_output_idx: int) -> None:
_script, htlc_tx = make_htlc_tx_with_open_channel(chan=self, _script, htlc_tx = make_htlc_tx_with_open_channel(chan=self,
pcp=pcp, pcp=pcp,
subject=LOCAL, subject=LOCAL,
@ -786,8 +760,8 @@ class Channel(Logger):
return max_send_msat return max_send_msat
def included_htlcs(self, subject: HTLCOwner, direction: Direction, ctn: int = None) -> Sequence[UpdateAddHtlc]: def included_htlcs(self, subject: HTLCOwner, direction: Direction, ctn: int = None) -> Sequence[UpdateAddHtlc]:
""" """Returns list of non-dust HTLCs for subject's commitment tx at ctn,
return filter of non-dust htlcs for subjects commitment transaction, initiated by given party filtered by direction (of HTLCs).
""" """
assert type(subject) is HTLCOwner assert type(subject) is HTLCOwner
assert type(direction) is Direction assert type(direction) is Direction
@ -859,14 +833,14 @@ class Channel(Logger):
def get_next_ctn(self, subject: HTLCOwner) -> int: def get_next_ctn(self, subject: HTLCOwner) -> int:
return self.hm.ctn_latest(subject) + 1 return self.hm.ctn_latest(subject) + 1
def total_msat(self, direction): def total_msat(self, direction: Direction) -> int:
"""Return the cumulative total msat amount received/sent so far.""" """Return the cumulative total msat amount received/sent so far."""
assert type(direction) is Direction assert type(direction) is Direction
return htlcsum(self.hm.all_settled_htlcs_ever_by_direction(LOCAL, direction)) return htlcsum(self.hm.all_settled_htlcs_ever_by_direction(LOCAL, direction))
def settle_htlc(self, preimage, htlc_id): def settle_htlc(self, preimage: bytes, htlc_id: int) -> None:
""" """Settle/fulfill a pending received HTLC.
SettleHTLC attempts to settle an existing outstanding received HTLC. Action must be initiated by LOCAL.
""" """
self.logger.info("settle_htlc") self.logger.info("settle_htlc")
assert self.can_send_ctx_updates(), f"cannot update channel. {self.get_state()!r} {self.peer_state!r}" assert self.can_send_ctx_updates(), f"cannot update channel. {self.get_state()!r} {self.peer_state!r}"
@ -889,7 +863,10 @@ class Channel(Logger):
self.onion_keys[htlc_id]) self.onion_keys[htlc_id])
return failure_msg, sender_idx return failure_msg, sender_idx
def receive_htlc_settle(self, preimage, htlc_id): def receive_htlc_settle(self, preimage: bytes, htlc_id: int) -> None:
"""Settle/fulfill a pending offered HTLC.
Action must be initiated by REMOTE.
"""
self.logger.info("receive_htlc_settle") self.logger.info("receive_htlc_settle")
log = self.hm.log[LOCAL] log = self.hm.log[LOCAL]
htlc = log['adds'][htlc_id] htlc = log['adds'][htlc_id]
@ -898,7 +875,10 @@ class Channel(Logger):
with self.db_lock: with self.db_lock:
self.hm.recv_settle(htlc_id) self.hm.recv_settle(htlc_id)
def fail_htlc(self, htlc_id): def fail_htlc(self, htlc_id: int) -> None:
"""Fail a pending received HTLC.
Action must be initiated by LOCAL.
"""
self.logger.info("fail_htlc") self.logger.info("fail_htlc")
assert self.can_send_ctx_updates(), f"cannot update channel. {self.get_state()!r} {self.peer_state!r}" assert self.can_send_ctx_updates(), f"cannot update channel. {self.get_state()!r} {self.peer_state!r}"
with self.db_lock: with self.db_lock:
@ -906,7 +886,10 @@ class Channel(Logger):
def receive_fail_htlc(self, htlc_id: int, *, def receive_fail_htlc(self, htlc_id: int, *,
error_bytes: Optional[bytes], error_bytes: Optional[bytes],
reason: Optional[OnionRoutingFailureMessage] = None): reason: Optional[OnionRoutingFailureMessage] = None) -> None:
"""Fail a pending offered HTLC.
Action must be initiated by REMOTE.
"""
self.logger.info("receive_fail_htlc") self.logger.info("receive_fail_htlc")
with self.db_lock: with self.db_lock:
self.hm.recv_fail(htlc_id) self.hm.recv_fail(htlc_id)

2
electrum/lnutil.py

@ -209,7 +209,7 @@ MAXIMUM_HTLC_MINIMUM_MSAT_ACCEPTED = 1000
MAXIMUM_REMOTE_TO_SELF_DELAY_ACCEPTED = 2016 MAXIMUM_REMOTE_TO_SELF_DELAY_ACCEPTED = 2016
class RevocationStore: class RevocationStore:
""" Taken from LND, see license in lnchannel.py. """ # closely based on code in lightningnetwork/lnd
START_INDEX = 2 ** 48 - 1 START_INDEX = 2 ** 48 - 1

3
electrum/tests/test_lnchannel.py

@ -18,6 +18,9 @@
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE. # THE SOFTWARE.
#
# Many of these unit tests are heavily based on unit tests in lnd
# (around commit 42de4400bff5105352d0552155f73589166d162b).
import unittest import unittest
import os import os

Loading…
Cancel
Save