Browse Source

lnhtlc: htlcs_by_direction now returns dict keyed by htlc_id

dependabot/pip/contrib/deterministic-build/ecdsa-0.13.3
SomberNight 6 years ago
committed by ThomasV
parent
commit
ce54b5411e
  1. 11
      electrum/lnchannel.py
  2. 22
      electrum/lnhtlc.py
  3. 8
      electrum/tests/test_lnchannel.py
  4. 2
      electrum/tests/test_lnhtlc.py

11
electrum/lnchannel.py

@ -200,7 +200,8 @@ class Channel(Logger):
raise PaymentFailure(f'Not enough local balance. Have: {self.available_to_spend(LOCAL)}, Need: {amount_msat}') raise PaymentFailure(f'Not enough local balance. Have: {self.available_to_spend(LOCAL)}, Need: {amount_msat}')
if len(self.hm.htlcs(LOCAL)) + 1 > self.config[REMOTE].max_accepted_htlcs: if len(self.hm.htlcs(LOCAL)) + 1 > self.config[REMOTE].max_accepted_htlcs:
raise PaymentFailure('Too many HTLCs already in channel') raise PaymentFailure('Too many HTLCs already in channel')
current_htlc_sum = htlcsum(self.hm.htlcs_by_direction(LOCAL, SENT)) + htlcsum(self.hm.htlcs_by_direction(LOCAL, RECEIVED)) current_htlc_sum = (htlcsum(self.hm.htlcs_by_direction(LOCAL, SENT).values())
+ htlcsum(self.hm.htlcs_by_direction(LOCAL, RECEIVED).values()))
if current_htlc_sum + amount_msat > self.config[REMOTE].max_htlc_value_in_flight_msat: if current_htlc_sum + amount_msat > self.config[REMOTE].max_htlc_value_in_flight_msat:
raise PaymentFailure(f'HTLC value sum (sum of pending htlcs: {current_htlc_sum/1000} sat plus new htlc: {amount_msat/1000} sat) would exceed max allowed: {self.config[REMOTE].max_htlc_value_in_flight_msat/1000} sat') raise PaymentFailure(f'HTLC value sum (sum of pending htlcs: {current_htlc_sum/1000} sat plus new htlc: {amount_msat/1000} sat) would exceed max allowed: {self.config[REMOTE].max_htlc_value_in_flight_msat/1000} sat')
if amount_msat < self.config[REMOTE].htlc_minimum_msat: if amount_msat < self.config[REMOTE].htlc_minimum_msat:
@ -451,7 +452,7 @@ class Channel(Logger):
assert type(whose) is HTLCOwner assert type(whose) is HTLCOwner
ctn = self.get_next_ctn(ctx_owner) ctn = self.get_next_ctn(ctx_owner)
return self.balance(whose, ctx_owner=ctx_owner, ctn=ctn)\ return self.balance(whose, ctx_owner=ctx_owner, ctn=ctn)\
- htlcsum(self.hm.htlcs_by_direction(ctx_owner, SENT, ctn)) - htlcsum(self.hm.htlcs_by_direction(ctx_owner, SENT, ctn).values())
def available_to_spend(self, subject): def available_to_spend(self, subject):
""" """
@ -484,7 +485,7 @@ class Channel(Logger):
weight = HTLC_SUCCESS_WEIGHT weight = HTLC_SUCCESS_WEIGHT
else: else:
weight = HTLC_TIMEOUT_WEIGHT weight = HTLC_TIMEOUT_WEIGHT
htlcs = self.hm.htlcs_by_direction(subject, direction, ctn=ctn) htlcs = self.hm.htlcs_by_direction(subject, direction, ctn=ctn).values()
fee_for_htlc = lambda htlc: htlc.amount_msat // 1000 - (weight * feerate // 1000) fee_for_htlc = lambda htlc: htlc.amount_msat // 1000 - (weight * feerate // 1000)
return list(filter(lambda htlc: fee_for_htlc(htlc) >= conf.dust_limit_sat, htlcs)) return list(filter(lambda htlc: fee_for_htlc(htlc) >= conf.dust_limit_sat, htlcs))
@ -647,8 +648,8 @@ class Channel(Logger):
other = REMOTE if LOCAL == subject else LOCAL other = REMOTE if LOCAL == subject else LOCAL
local_msat = self.balance(subject, ctx_owner=subject, ctn=ctn) local_msat = self.balance(subject, ctx_owner=subject, ctn=ctn)
remote_msat = self.balance(other, ctx_owner=subject, ctn=ctn) remote_msat = self.balance(other, ctx_owner=subject, ctn=ctn)
received_htlcs = self.hm.htlcs_by_direction(subject, SENT if subject == LOCAL else RECEIVED, ctn) received_htlcs = self.hm.htlcs_by_direction(subject, SENT if subject == LOCAL else RECEIVED, ctn).values()
sent_htlcs = self.hm.htlcs_by_direction(subject, RECEIVED if subject == LOCAL else SENT, ctn) sent_htlcs = self.hm.htlcs_by_direction(subject, RECEIVED if subject == LOCAL else SENT, ctn).values()
if subject != LOCAL: if subject != LOCAL:
remote_msat -= htlcsum(received_htlcs) remote_msat -= htlcsum(received_htlcs)
local_msat -= htlcsum(sent_htlcs) local_msat -= htlcsum(sent_htlcs)

22
electrum/lnhtlc.py

@ -25,7 +25,7 @@ class HTLCManager:
log = {(HTLCOwner(int(k)) if k in ("-1", "1") else k): v log = {(HTLCOwner(int(k)) if k in ("-1", "1") else k): v
for k, v in deepcopy(log).items()} for k, v in deepcopy(log).items()}
for sub in (LOCAL, REMOTE): for sub in (LOCAL, REMOTE):
log[sub]['adds'] = {int(x): UpdateAddHtlc(*y) for x, y in log[sub]['adds'].items()} log[sub]['adds'] = {int(htlc_id): UpdateAddHtlc(*htlc) for htlc_id, htlc in log[sub]['adds'].items()}
coerceHtlcOwner2IntMap = lambda ctns: {HTLCOwner(int(owner)): ctn for owner, ctn in ctns.items()} coerceHtlcOwner2IntMap = lambda ctns: {HTLCOwner(int(owner)): ctn for owner, ctn in ctns.items()}
# "side who offered htlc" -> action -> htlc_id -> whose ctx -> ctn # "side who offered htlc" -> action -> htlc_id -> whose ctx -> ctn
log[sub]['locked_in'] = {int(htlc_id): coerceHtlcOwner2IntMap(ctns) for htlc_id, ctns in log[sub]['locked_in'].items()} log[sub]['locked_in'] = {int(htlc_id): coerceHtlcOwner2IntMap(ctns) for htlc_id, ctns in log[sub]['locked_in'].items()}
@ -222,9 +222,9 @@ class HTLCManager:
##### Queries re HTLCs: ##### Queries re HTLCs:
def htlcs_by_direction(self, subject: HTLCOwner, direction: Direction, def htlcs_by_direction(self, subject: HTLCOwner, direction: Direction,
ctn: int = None) -> Sequence[UpdateAddHtlc]: ctn: int = None) -> Dict[int, UpdateAddHtlc]:
"""Return the list of received or sent (depending on direction) HTLCs """Return the dict of received or sent (depending on direction) HTLCs
in subject's ctx at ctn. in subject's ctx at ctn, keyed by htlc_id.
direction is relative to subject! direction is relative to subject!
""" """
@ -232,19 +232,19 @@ class HTLCManager:
assert type(direction) is Direction assert type(direction) is Direction
if ctn is None: if ctn is None:
ctn = self.ctn_oldest_unrevoked(subject) ctn = self.ctn_oldest_unrevoked(subject)
l = [] d = {}
# subject's ctx # subject's ctx
# party is the proposer of the HTLCs # party is the proposer of the HTLCs
party = subject if direction == SENT else subject.inverted() party = subject if direction == SENT else subject.inverted()
settles = self.log[party]['settles']
fails = self.log[party]['fails']
for htlc_id, ctns in self.log[party]['locked_in'].items(): for htlc_id, ctns in self.log[party]['locked_in'].items():
if ctns[subject] is not None and ctns[subject] <= ctn: if ctns[subject] is not None and ctns[subject] <= ctn:
settles = self.log[party]['settles']
fails = self.log[party]['fails']
not_settled = htlc_id not in settles or settles[htlc_id][subject] is None or settles[htlc_id][subject] > ctn not_settled = htlc_id not in settles or settles[htlc_id][subject] is None or settles[htlc_id][subject] > ctn
not_failed = htlc_id not in fails or fails[htlc_id][subject] is None or fails[htlc_id][subject] > ctn not_failed = htlc_id not in fails or fails[htlc_id][subject] is None or fails[htlc_id][subject] > ctn
if not_settled and not_failed: if not_settled and not_failed:
l.append(self.log[party]['adds'][htlc_id]) d[htlc_id] = self.log[party]['adds'][htlc_id]
return l return d
def htlcs(self, subject: HTLCOwner, ctn: int = None) -> Sequence[Tuple[Direction, UpdateAddHtlc]]: def htlcs(self, subject: HTLCOwner, ctn: int = None) -> Sequence[Tuple[Direction, UpdateAddHtlc]]:
"""Return the list of HTLCs in subject's ctx at ctn.""" """Return the list of HTLCs in subject's ctx at ctn."""
@ -252,8 +252,8 @@ class HTLCManager:
if ctn is None: if ctn is None:
ctn = self.ctn_oldest_unrevoked(subject) ctn = self.ctn_oldest_unrevoked(subject)
l = [] l = []
l += [(SENT, x) for x in self.htlcs_by_direction(subject, SENT, ctn)] l += [(SENT, x) for x in self.htlcs_by_direction(subject, SENT, ctn).values()]
l += [(RECEIVED, x) for x in self.htlcs_by_direction(subject, RECEIVED, ctn)] l += [(RECEIVED, x) for x in self.htlcs_by_direction(subject, RECEIVED, ctn).values()]
return l return l
def get_htlcs_in_oldest_unrevoked_ctx(self, subject: HTLCOwner) -> Sequence[Tuple[Direction, UpdateAddHtlc]]: def get_htlcs_in_oldest_unrevoked_ctx(self, subject: HTLCOwner) -> Sequence[Tuple[Direction, UpdateAddHtlc]]:

8
electrum/tests/test_lnchannel.py

@ -202,7 +202,7 @@ class TestChannel(unittest.TestCase):
# update log. Then Alice sends this wire message over to Bob who adds # update log. Then Alice sends this wire message over to Bob who adds
# this htlc to his remote state update log. # this htlc to his remote state update log.
self.aliceHtlcIndex = self.alice_channel.add_htlc(self.htlc_dict).htlc_id self.aliceHtlcIndex = self.alice_channel.add_htlc(self.htlc_dict).htlc_id
self.assertNotEqual(self.alice_channel.hm.htlcs_by_direction(REMOTE, RECEIVED, 1), []) self.assertNotEqual(list(self.alice_channel.hm.htlcs_by_direction(REMOTE, RECEIVED, 1).values()), [])
before = self.bob_channel.balance_minus_outgoing_htlcs(REMOTE) before = self.bob_channel.balance_minus_outgoing_htlcs(REMOTE)
beforeLocal = self.bob_channel.balance_minus_outgoing_htlcs(LOCAL) beforeLocal = self.bob_channel.balance_minus_outgoing_htlcs(LOCAL)
@ -414,7 +414,7 @@ class TestChannel(unittest.TestCase):
bobSig2, bobHtlcSigs2 = bob_channel.sign_next_commitment() bobSig2, bobHtlcSigs2 = bob_channel.sign_next_commitment()
self.assertEqual(len(bobHtlcSigs2), 0) self.assertEqual(len(bobHtlcSigs2), 0)
self.assertEqual(alice_channel.hm.htlcs_by_direction(REMOTE, RECEIVED), [htlc]) self.assertEqual(list(alice_channel.hm.htlcs_by_direction(REMOTE, RECEIVED).values()), [htlc])
self.assertEqual(alice_channel.included_htlcs(REMOTE, RECEIVED, alice_channel.get_oldest_unrevoked_ctn(REMOTE)), [htlc]) self.assertEqual(alice_channel.included_htlcs(REMOTE, RECEIVED, alice_channel.get_oldest_unrevoked_ctn(REMOTE)), [htlc])
self.assertEqual(alice_channel.included_htlcs(REMOTE, RECEIVED, 1), [htlc]) self.assertEqual(alice_channel.included_htlcs(REMOTE, RECEIVED, 1), [htlc])
@ -693,9 +693,9 @@ class TestChanReserve(unittest.TestCase):
force_state_transition(self.alice_channel, self.bob_channel) force_state_transition(self.alice_channel, self.bob_channel)
aliceSelfBalance = self.alice_channel.balance(LOCAL)\ aliceSelfBalance = self.alice_channel.balance(LOCAL)\
- lnchannel.htlcsum(self.alice_channel.hm.htlcs_by_direction(LOCAL, SENT)) - lnchannel.htlcsum(self.alice_channel.hm.htlcs_by_direction(LOCAL, SENT).values())
bobBalance = self.bob_channel.balance(REMOTE)\ bobBalance = self.bob_channel.balance(REMOTE)\
- lnchannel.htlcsum(self.alice_channel.hm.htlcs_by_direction(REMOTE, SENT)) - lnchannel.htlcsum(self.alice_channel.hm.htlcs_by_direction(REMOTE, SENT).values())
self.assertEqual(aliceSelfBalance, one_bitcoin_in_msat*4.5) self.assertEqual(aliceSelfBalance, one_bitcoin_in_msat*4.5)
self.assertEqual(bobBalance, one_bitcoin_in_msat*5) self.assertEqual(bobBalance, one_bitcoin_in_msat*5)
# Now let Bob try to add an HTLC. This should fail, since it will # Now let Bob try to add an HTLC. This should fail, since it will

2
electrum/tests/test_lnhtlc.py

@ -82,7 +82,7 @@ class TestHTLCManager(unittest.TestCase):
else: else:
B.send_fail(0) B.send_fail(0)
A.recv_fail(0) A.recv_fail(0)
self.assertEqual(A.htlcs_by_direction(REMOTE, RECEIVED), [H('A', 0)]) self.assertEqual(list(A.htlcs_by_direction(REMOTE, RECEIVED).values()), [H('A', 0)])
self.assertNotEqual(A.get_htlcs_in_latest_ctx(LOCAL), []) self.assertNotEqual(A.get_htlcs_in_latest_ctx(LOCAL), [])
self.assertNotEqual(B.get_htlcs_in_latest_ctx(REMOTE), []) self.assertNotEqual(B.get_htlcs_in_latest_ctx(REMOTE), [])

Loading…
Cancel
Save