Browse Source

lnhtlc: move 'next_htlc_id' from ChannelConfig to lnhtlc log

dependabot/pip/contrib/deterministic-build/ecdsa-0.13.3
SomberNight 6 years ago
committed by ThomasV
parent
commit
c046f2cc1c
  1. 8
      electrum/lnchannel.py
  2. 12
      electrum/lnhtlc.py
  3. 10
      electrum/lnpeer.py
  4. 2
      electrum/lnutil.py
  5. 2
      electrum/tests/test_lnchannel.py

8
electrum/lnchannel.py

@ -243,10 +243,10 @@ class Channel(Logger):
htlc = UpdateAddHtlc(**htlc) htlc = UpdateAddHtlc(**htlc)
assert isinstance(htlc, UpdateAddHtlc) assert isinstance(htlc, UpdateAddHtlc)
self._check_can_pay(htlc.amount_msat) self._check_can_pay(htlc.amount_msat)
htlc = htlc._replace(htlc_id=self.config[LOCAL].next_htlc_id) if htlc.htlc_id is None:
htlc = htlc._replace(htlc_id=self.hm.get_next_htlc_id(LOCAL))
self.hm.send_htlc(htlc) self.hm.send_htlc(htlc)
self.logger.info("add_htlc") self.logger.info("add_htlc")
self.config[LOCAL]=self.config[LOCAL]._replace(next_htlc_id=htlc.htlc_id + 1)
return htlc return htlc
def receive_htlc(self, htlc: UpdateAddHtlc) -> UpdateAddHtlc: def receive_htlc(self, htlc: UpdateAddHtlc) -> UpdateAddHtlc:
@ -260,14 +260,14 @@ class Channel(Logger):
if isinstance(htlc, dict): # legacy conversion # FIXME remove if isinstance(htlc, dict): # legacy conversion # FIXME remove
htlc = UpdateAddHtlc(**htlc) htlc = UpdateAddHtlc(**htlc)
assert isinstance(htlc, UpdateAddHtlc) assert isinstance(htlc, UpdateAddHtlc)
htlc = htlc._replace(htlc_id=self.config[REMOTE].next_htlc_id) if htlc.htlc_id is None: # used in unit tests
htlc = htlc._replace(htlc_id=self.hm.get_next_htlc_id(REMOTE))
if 0 <= self.available_to_spend(REMOTE) < htlc.amount_msat: if 0 <= self.available_to_spend(REMOTE) < htlc.amount_msat:
raise RemoteMisbehaving('Remote dipped below channel reserve.' +\ raise RemoteMisbehaving('Remote dipped below channel reserve.' +\
f' Available at remote: {self.available_to_spend(REMOTE)},' +\ f' Available at remote: {self.available_to_spend(REMOTE)},' +\
f' HTLC amount: {htlc.amount_msat}') f' HTLC amount: {htlc.amount_msat}')
self.hm.recv_htlc(htlc) self.hm.recv_htlc(htlc)
self.logger.info("receive_htlc") self.logger.info("receive_htlc")
self.config[REMOTE]=self.config[REMOTE]._replace(next_htlc_id=htlc.htlc_id + 1)
return htlc return htlc
def sign_next_commitment(self): def sign_next_commitment(self):

12
electrum/lnhtlc.py

@ -18,6 +18,7 @@ class HTLCManager:
'fails': {}, 'fails': {},
'fee_updates': [], 'fee_updates': [],
'revack_pending': False, 'revack_pending': False,
'next_htlc_id': 0,
} }
log = {LOCAL: deepcopy(initial), REMOTE: deepcopy(initial)} log = {LOCAL: deepcopy(initial), REMOTE: deepcopy(initial)}
else: else:
@ -54,6 +55,9 @@ class HTLCManager:
def _set_revack_pending(self, sub: HTLCOwner, pending: bool) -> None: def _set_revack_pending(self, sub: HTLCOwner, pending: bool) -> None:
self.log[sub]['revack_pending'] = pending self.log[sub]['revack_pending'] = pending
def get_next_htlc_id(self, sub: HTLCOwner) -> int:
return self.log[sub]['next_htlc_id']
def to_save(self): def to_save(self):
log = deepcopy(self.log) log = deepcopy(self.log)
for sub in (LOCAL, REMOTE): for sub in (LOCAL, REMOTE):
@ -75,14 +79,22 @@ class HTLCManager:
def send_htlc(self, htlc: UpdateAddHtlc) -> UpdateAddHtlc: def send_htlc(self, htlc: UpdateAddHtlc) -> UpdateAddHtlc:
htlc_id = htlc.htlc_id htlc_id = htlc.htlc_id
if htlc_id != self.get_next_htlc_id(LOCAL):
raise Exception(f"unexpected local htlc_id. next should be "
f"{self.get_next_htlc_id(LOCAL)} but got {htlc_id}")
self.log[LOCAL]['adds'][htlc_id] = htlc self.log[LOCAL]['adds'][htlc_id] = htlc
self.log[LOCAL]['locked_in'][htlc_id] = {LOCAL: None, REMOTE: self.ctn_latest(REMOTE)+1} self.log[LOCAL]['locked_in'][htlc_id] = {LOCAL: None, REMOTE: self.ctn_latest(REMOTE)+1}
self.log[LOCAL]['next_htlc_id'] += 1
return htlc return htlc
def recv_htlc(self, htlc: UpdateAddHtlc) -> None: def recv_htlc(self, htlc: UpdateAddHtlc) -> None:
htlc_id = htlc.htlc_id htlc_id = htlc.htlc_id
if htlc_id != self.get_next_htlc_id(REMOTE):
raise Exception(f"unexpected remote htlc_id. next should be "
f"{self.get_next_htlc_id(REMOTE)} but got {htlc_id}")
self.log[REMOTE]['adds'][htlc_id] = htlc self.log[REMOTE]['adds'][htlc_id] = htlc
self.log[REMOTE]['locked_in'][htlc_id] = {LOCAL: self.ctn_latest(LOCAL)+1, REMOTE: None} self.log[REMOTE]['locked_in'][htlc_id] = {LOCAL: self.ctn_latest(LOCAL)+1, REMOTE: None}
self.log[REMOTE]['next_htlc_id'] += 1
def send_settle(self, htlc_id: int) -> None: def send_settle(self, htlc_id: int) -> None:
self.log[REMOTE]['settles'][htlc_id] = {LOCAL: None, REMOTE: self.ctn_latest(REMOTE) + 1} self.log[REMOTE]['settles'][htlc_id] = {LOCAL: None, REMOTE: self.ctn_latest(REMOTE) + 1}

10
electrum/lnpeer.py

@ -434,7 +434,6 @@ class Peer(Logger):
max_accepted_htlcs=5, max_accepted_htlcs=5,
initial_msat=initial_msat, initial_msat=initial_msat,
ctn=-1, ctn=-1,
next_htlc_id=0,
reserve_sat=546, reserve_sat=546,
per_commitment_secret_seed=keypair_generator(LnKeyFamily.REVOCATION_ROOT).privkey, per_commitment_secret_seed=keypair_generator(LnKeyFamily.REVOCATION_ROOT).privkey,
funding_locked_received=False, funding_locked_received=False,
@ -518,7 +517,6 @@ class Peer(Logger):
max_accepted_htlcs=max_accepted_htlcs, max_accepted_htlcs=max_accepted_htlcs,
initial_msat=push_msat, initial_msat=push_msat,
ctn = -1, ctn = -1,
next_htlc_id = 0,
reserve_sat = remote_reserve_sat, reserve_sat = remote_reserve_sat,
htlc_minimum_msat = htlc_min, htlc_minimum_msat = htlc_min,
@ -621,7 +619,6 @@ class Peer(Logger):
max_accepted_htlcs=int.from_bytes(payload['max_accepted_htlcs'], 'big'), # TODO validate max_accepted_htlcs=int.from_bytes(payload['max_accepted_htlcs'], 'big'), # TODO validate
initial_msat=remote_balance_sat, initial_msat=remote_balance_sat,
ctn = -1, ctn = -1,
next_htlc_id = 0,
reserve_sat = remote_reserve_sat, reserve_sat = remote_reserve_sat,
htlc_minimum_msat=int.from_bytes(payload['htlc_minimum_msat'], 'big'), # TODO validate htlc_minimum_msat=int.from_bytes(payload['htlc_minimum_msat'], 'big'), # TODO validate
next_per_commitment_point=payload['first_per_commitment_point'], next_per_commitment_point=payload['first_per_commitment_point'],
@ -1142,11 +1139,14 @@ class Peer(Logger):
processed_onion = process_onion_packet(onion_packet, associated_data=payment_hash, our_onion_private_key=self.privkey) processed_onion = process_onion_packet(onion_packet, associated_data=payment_hash, our_onion_private_key=self.privkey)
chan = self.channels[channel_id] chan = self.channels[channel_id]
assert chan.get_state() == "OPEN" assert chan.get_state() == "OPEN"
assert htlc_id == chan.config[REMOTE].next_htlc_id, (htlc_id, chan.config[REMOTE].next_htlc_id) # TODO fail channel instead
if cltv_expiry >= 500_000_000: if cltv_expiry >= 500_000_000:
pass # TODO fail the channel pass # TODO fail the channel
# add htlc # add htlc
htlc = UpdateAddHtlc(amount_msat=amount_msat_htlc, payment_hash=payment_hash, cltv_expiry=cltv_expiry, timestamp=int(time.time())) htlc = UpdateAddHtlc(amount_msat=amount_msat_htlc,
payment_hash=payment_hash,
cltv_expiry=cltv_expiry,
timestamp=int(time.time()),
htlc_id=htlc_id)
htlc = chan.receive_htlc(htlc) htlc = chan.receive_htlc(htlc)
local_ctn = chan.get_current_ctn(LOCAL) local_ctn = chan.get_current_ctn(LOCAL)
remote_ctn = chan.get_current_ctn(REMOTE) remote_ctn = chan.get_current_ctn(REMOTE)

2
electrum/lnutil.py

@ -35,7 +35,6 @@ OnlyPubkeyKeypair = namedtuple("OnlyPubkeyKeypair", ["pubkey"])
class LocalConfig(NamedTuple): class LocalConfig(NamedTuple):
# shared channel config fields (DUPLICATED code!!) # shared channel config fields (DUPLICATED code!!)
ctn: int ctn: int
next_htlc_id: int
payment_basepoint: 'Keypair' payment_basepoint: 'Keypair'
multisig_key: 'Keypair' multisig_key: 'Keypair'
htlc_basepoint: 'Keypair' htlc_basepoint: 'Keypair'
@ -59,7 +58,6 @@ class LocalConfig(NamedTuple):
class RemoteConfig(NamedTuple): class RemoteConfig(NamedTuple):
# shared channel config fields (DUPLICATED code!!) # shared channel config fields (DUPLICATED code!!)
ctn: int ctn: int
next_htlc_id: int
payment_basepoint: 'Keypair' payment_basepoint: 'Keypair'
multisig_key: 'Keypair' multisig_key: 'Keypair'
htlc_basepoint: 'Keypair' htlc_basepoint: 'Keypair'

2
electrum/tests/test_lnchannel.py

@ -59,7 +59,6 @@ def create_channel_state(funding_txid, funding_index, funding_sat, is_initiator,
max_accepted_htlcs=5, max_accepted_htlcs=5,
initial_msat=remote_amount, initial_msat=remote_amount,
ctn = -1, ctn = -1,
next_htlc_id = 0,
reserve_sat=0, reserve_sat=0,
htlc_minimum_msat=1, htlc_minimum_msat=1,
@ -79,7 +78,6 @@ def create_channel_state(funding_txid, funding_index, funding_sat, is_initiator,
max_accepted_htlcs=5, max_accepted_htlcs=5,
initial_msat=local_amount, initial_msat=local_amount,
ctn = 0, ctn = 0,
next_htlc_id = 0,
reserve_sat=0, reserve_sat=0,
per_commitment_secret_seed=seed, per_commitment_secret_seed=seed,

Loading…
Cancel
Save