Browse Source

lnchannel: add_htlc and receive_htlc now take and return UpdateAddHtlc

also fix undefined vars in _maybe_forward_htlc and _maybe_fulfill_htlc
in lnpeer
regtest_lnd
SomberNight 6 years ago
parent
commit
a1c68e49b7
No known key found for this signature in database GPG Key ID: B33B5F232C6271E9
  1. 22
      electrum/lnchannel.py
  2. 91
      electrum/lnpeer.py
  3. 17
      electrum/lnutil.py
  4. 26
      electrum/tests/test_lnchannel.py

22
electrum/lnchannel.py

@ -241,22 +241,24 @@ class Channel(PrintError):
script = funding_output_script(self.config[LOCAL], self.config[REMOTE]) script = funding_output_script(self.config[LOCAL], self.config[REMOTE])
return redeem_script_to_address('p2wsh', script) return redeem_script_to_address('p2wsh', script)
def add_htlc(self, htlc): def add_htlc(self, htlc: UpdateAddHtlc) -> UpdateAddHtlc:
""" """
AddHTLC adds an HTLC to the state machine's local update log. This method AddHTLC adds an HTLC to the state machine's local update log. This method
should be called when preparing to send an outgoing HTLC. should be called when preparing to send an outgoing HTLC.
This docstring is from LND. This docstring is from LND.
""" """
assert type(htlc) is dict if isinstance(htlc, dict): # legacy conversion # FIXME remove
self._check_can_pay(htlc['amount_msat']) htlc = UpdateAddHtlc(**htlc)
htlc = UpdateAddHtlc(**htlc, htlc_id=self.config[LOCAL].next_htlc_id) assert isinstance(htlc, UpdateAddHtlc)
self._check_can_pay(htlc.amount_msat)
htlc = htlc._replace(htlc_id=self.config[LOCAL].next_htlc_id)
self.hm.send_htlc(htlc) self.hm.send_htlc(htlc)
self.print_error("add_htlc") self.print_error("add_htlc")
self.config[LOCAL]=self.config[LOCAL]._replace(next_htlc_id=htlc.htlc_id + 1) self.config[LOCAL]=self.config[LOCAL]._replace(next_htlc_id=htlc.htlc_id + 1)
return htlc.htlc_id return htlc
def receive_htlc(self, htlc): def receive_htlc(self, htlc: UpdateAddHtlc) -> UpdateAddHtlc:
""" """
ReceiveHTLC adds an HTLC to the state machine's remote update log. This ReceiveHTLC adds an HTLC to the state machine's remote update log. This
method should be called in response to receiving a new HTLC from the remote method should be called in response to receiving a new HTLC from the remote
@ -264,8 +266,10 @@ class Channel(PrintError):
This docstring is from LND. This docstring is from LND.
""" """
assert type(htlc) is dict if isinstance(htlc, dict): # legacy conversion # FIXME remove
htlc = UpdateAddHtlc(**htlc, htlc_id = self.config[REMOTE].next_htlc_id) htlc = UpdateAddHtlc(**htlc)
assert isinstance(htlc, UpdateAddHtlc)
htlc = htlc._replace(htlc_id=self.config[REMOTE].next_htlc_id)
if self.available_to_spend(REMOTE) < htlc.amount_msat: if 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)},' +\
@ -273,7 +277,7 @@ class Channel(PrintError):
self.hm.recv_htlc(htlc) self.hm.recv_htlc(htlc)
self.print_error("receive_htlc") self.print_error("receive_htlc")
self.config[REMOTE]=self.config[REMOTE]._replace(next_htlc_id=htlc.htlc_id + 1) self.config[REMOTE]=self.config[REMOTE]._replace(next_htlc_id=htlc.htlc_id + 1)
return htlc.htlc_id return htlc
def sign_next_commitment(self): def sign_next_commitment(self):
""" """

91
electrum/lnpeer.py

@ -25,7 +25,8 @@ from . import constants
from .util import PrintError, bh2u, print_error, bfh, log_exceptions, list_enabled_bits, ignore_exceptions from .util import PrintError, bh2u, print_error, bfh, log_exceptions, list_enabled_bits, ignore_exceptions
from .transaction import Transaction, TxOutput from .transaction import Transaction, TxOutput
from .lnonion import (new_onion_packet, decode_onion_error, OnionFailureCode, calc_hops_data_for_payment, from .lnonion import (new_onion_packet, decode_onion_error, OnionFailureCode, calc_hops_data_for_payment,
process_onion_packet, OnionPacket, construct_onion_error, OnionRoutingFailureMessage) process_onion_packet, OnionPacket, construct_onion_error, OnionRoutingFailureMessage,
ProcessedOnionPacket)
from .lnchannel import Channel, RevokeAndAck, htlcsum from .lnchannel import Channel, RevokeAndAck, htlcsum
from .lnutil import (Outpoint, LocalConfig, RECEIVED, UpdateAddHtlc, from .lnutil import (Outpoint, LocalConfig, RECEIVED, UpdateAddHtlc,
RemoteConfig, OnlyPubkeyKeypair, ChannelConstraints, RevocationStore, RemoteConfig, OnlyPubkeyKeypair, ChannelConstraints, RevocationStore,
@ -841,7 +842,7 @@ class Peer(PrintError):
await self._local_changed_events[chan.channel_id].wait() await self._local_changed_events[chan.channel_id].wait()
async def pay(self, route: List['RouteEdge'], chan: Channel, amount_msat: int, async def pay(self, route: List['RouteEdge'], chan: Channel, amount_msat: int,
payment_hash: bytes, min_final_cltv_expiry: int): payment_hash: bytes, min_final_cltv_expiry: int) -> UpdateAddHtlc:
assert chan.get_state() == "OPEN", chan.get_state() assert chan.get_state() == "OPEN", chan.get_state()
assert amount_msat > 0, "amount_msat is not greater zero" assert amount_msat > 0, "amount_msat is not greater zero"
# create onion packet # create onion packet
@ -851,22 +852,22 @@ class Peer(PrintError):
secret_key = os.urandom(32) secret_key = os.urandom(32)
onion = new_onion_packet([x.node_id for x in route], secret_key, hops_data, associated_data=payment_hash) onion = new_onion_packet([x.node_id for x in route], secret_key, hops_data, associated_data=payment_hash)
# create htlc # create htlc
htlc = {'amount_msat':amount_msat, 'payment_hash':payment_hash, 'cltv_expiry':cltv} htlc = UpdateAddHtlc(amount_msat=amount_msat, payment_hash=payment_hash, cltv_expiry=cltv)
htlc_id = chan.add_htlc(htlc) htlc = chan.add_htlc(htlc)
remote_ctn = chan.get_current_ctn(REMOTE) remote_ctn = chan.get_current_ctn(REMOTE)
chan.onion_keys[htlc_id] = secret_key chan.onion_keys[htlc.htlc_id] = secret_key
self.attempted_route[(chan.channel_id, htlc_id)] = route self.attempted_route[(chan.channel_id, htlc.htlc_id)] = route
self.print_error(f"starting payment. route: {route}") self.print_error(f"starting payment. route: {route}")
self.send_message("update_add_htlc", self.send_message("update_add_htlc",
channel_id=chan.channel_id, channel_id=chan.channel_id,
id=htlc_id, id=htlc.htlc_id,
cltv_expiry=cltv, cltv_expiry=htlc.cltv_expiry,
amount_msat=amount_msat, amount_msat=htlc.amount_msat,
payment_hash=payment_hash, payment_hash=htlc.payment_hash,
onion_routing_packet=onion.to_bytes()) onion_routing_packet=onion.to_bytes())
self.remote_pending_updates[chan] = True self.remote_pending_updates[chan] = True
await self.await_remote(chan, remote_ctn) await self.await_remote(chan, remote_ctn)
return UpdateAddHtlc(**htlc, htlc_id=htlc_id) return htlc
def send_revoke_and_ack(self, chan: Channel): def send_revoke_and_ack(self, chan: Channel):
rev, _ = chan.revoke_current_commitment() rev, _ = chan.revoke_current_commitment()
@ -923,18 +924,29 @@ class Peer(PrintError):
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 = {'amount_msat': amount_msat_htlc, 'payment_hash':payment_hash, 'cltv_expiry':cltv_expiry} htlc = UpdateAddHtlc(amount_msat=amount_msat_htlc, payment_hash=payment_hash, cltv_expiry=cltv_expiry)
htlc_id = chan.receive_htlc(htlc) htlc = chan.receive_htlc(htlc)
self.local_pending_updates[chan] = True self.local_pending_updates[chan] = True
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)
if processed_onion.are_we_final: if processed_onion.are_we_final:
asyncio.ensure_future(self._maybe_fulfill_htlc(chan, local_ctn, remote_ctn, htlc_id, htlc, payment_hash, cltv_expiry, amount_msat_htlc, processed_onion)) asyncio.ensure_future(self._maybe_fulfill_htlc(chan=chan,
htlc=htlc,
local_ctn=local_ctn,
remote_ctn=remote_ctn,
onion_packet=onion_packet,
processed_onion=processed_onion))
else: else:
asyncio.ensure_future(self._maybe_forward_htlc(chan, local_ctn, remote_ctn, htlc_id, htlc, payment_hash, cltv_expiry, amount_msat_htlc, processed_onion)) asyncio.ensure_future(self._maybe_forward_htlc(chan=chan,
htlc=htlc,
local_ctn=local_ctn,
remote_ctn=remote_ctn,
onion_packet=onion_packet,
processed_onion=processed_onion))
@log_exceptions @log_exceptions
async def _maybe_forward_htlc(self, chan, local_ctn, remote_ctn, htlc_id, htlc, payment_hash, cltv_expiry, amount_msat_htlc, processed_onion): async def _maybe_forward_htlc(self, chan: Channel, htlc: UpdateAddHtlc, *, local_ctn: int, remote_ctn: int,
onion_packet: OnionPacket, processed_onion: ProcessedOnionPacket):
await self.await_local(chan, local_ctn) await self.await_local(chan, local_ctn)
await self.await_remote(chan, remote_ctn) await self.await_remote(chan, remote_ctn)
# Forward HTLC # Forward HTLC
@ -945,69 +957,70 @@ class Peer(PrintError):
if next_chan is None or next_chan.get_state() != 'OPEN': if next_chan is None or next_chan.get_state() != 'OPEN':
self.print_error("cannot forward htlc", next_chan.get_state() if next_chan else None) self.print_error("cannot forward htlc", next_chan.get_state() if next_chan else None)
reason = OnionRoutingFailureMessage(code=OnionFailureCode.PERMANENT_CHANNEL_FAILURE, data=b'') reason = OnionRoutingFailureMessage(code=OnionFailureCode.PERMANENT_CHANNEL_FAILURE, data=b'')
await self.fail_htlc(chan, htlc_id, onion_packet, reason) await self.fail_htlc(chan, htlc.htlc_id, onion_packet, reason)
return return
self.print_error('forwarding htlc to', next_chan.node_id) self.print_error('forwarding htlc to', next_chan.node_id)
next_cltv_expiry = int.from_bytes(dph.outgoing_cltv_value, 'big') next_cltv_expiry = int.from_bytes(dph.outgoing_cltv_value, 'big')
next_amount_msat_htlc = int.from_bytes(dph.amt_to_forward, 'big') next_amount_msat_htlc = int.from_bytes(dph.amt_to_forward, 'big')
next_htlc = {'amount_msat':next_amount_msat_htlc, 'payment_hash':payment_hash, 'cltv_expiry':next_cltv_expiry} next_htlc = UpdateAddHtlc(amount_msat=next_amount_msat_htlc, payment_hash=htlc.payment_hash, cltv_expiry=next_cltv_expiry)
next_htlc_id = next_chan.add_htlc(next_htlc) next_htlc = next_chan.add_htlc(next_htlc)
next_remote_ctn = next_chan.get_current_ctn(REMOTE) next_remote_ctn = next_chan.get_current_ctn(REMOTE)
next_peer.send_message( next_peer.send_message(
"update_add_htlc", "update_add_htlc",
channel_id=next_chan.channel_id, channel_id=next_chan.channel_id,
id=next_htlc_id, id=next_htlc.htlc_id,
cltv_expiry=dph.outgoing_cltv_value, cltv_expiry=dph.outgoing_cltv_value,
amount_msat=dph.amt_to_forward, amount_msat=dph.amt_to_forward,
payment_hash=payment_hash, payment_hash=next_htlc.payment_hash,
onion_routing_packet=processed_onion.next_packet.to_bytes() onion_routing_packet=processed_onion.next_packet.to_bytes()
) )
next_peer.remote_pending_updates[next_chan] = True next_peer.remote_pending_updates[next_chan] = True
await next_peer.await_remote(next_chan, next_remote_ctn) await next_peer.await_remote(next_chan, next_remote_ctn)
# wait until we get paid # wait until we get paid
preimage = await next_peer.payment_preimages[payment_hash].get() preimage = await next_peer.payment_preimages[next_htlc.payment_hash].get()
# fulfill the original htlc # fulfill the original htlc
await self._fulfill_htlc(chan, htlc_id, preimage) await self._fulfill_htlc(chan, htlc.htlc_id, preimage)
self.print_error("htlc forwarded successfully") self.print_error("htlc forwarded successfully")
@log_exceptions @log_exceptions
async def _maybe_fulfill_htlc(self, chan, local_ctn, remote_ctn, htlc_id, htlc, payment_hash, cltv_expiry, amount_msat_htlc, processed_onion): async def _maybe_fulfill_htlc(self, chan: Channel, htlc: UpdateAddHtlc, *, local_ctn: int, remote_ctn: int,
onion_packet: OnionPacket, processed_onion: ProcessedOnionPacket):
await self.await_local(chan, local_ctn) await self.await_local(chan, local_ctn)
await self.await_remote(chan, remote_ctn) await self.await_remote(chan, remote_ctn)
try: try:
invoice = self.lnworker.get_invoice(payment_hash) invoice = self.lnworker.get_invoice(htlc.payment_hash)
preimage = self.lnworker.get_preimage(payment_hash) preimage = self.lnworker.get_preimage(htlc.payment_hash)
except UnknownPaymentHash: except UnknownPaymentHash:
reason = OnionRoutingFailureMessage(code=OnionFailureCode.UNKNOWN_PAYMENT_HASH, data=b'') reason = OnionRoutingFailureMessage(code=OnionFailureCode.UNKNOWN_PAYMENT_HASH, data=b'')
await self.fail_htlc(chan, htlc_id, onion_packet, reason) await self.fail_htlc(chan, htlc.htlc_id, onion_packet, reason)
return return
expected_received_msat = int(invoice.amount * bitcoin.COIN * 1000) if invoice.amount is not None else None expected_received_msat = int(invoice.amount * bitcoin.COIN * 1000) if invoice.amount is not None else None
if expected_received_msat is not None and \ if expected_received_msat is not None and \
(amount_msat_htlc < expected_received_msat or amount_msat_htlc > 2 * expected_received_msat): (htlc.amount_msat < expected_received_msat or htlc.amount_msat > 2 * expected_received_msat):
reason = OnionRoutingFailureMessage(code=OnionFailureCode.INCORRECT_PAYMENT_AMOUNT, data=b'') reason = OnionRoutingFailureMessage(code=OnionFailureCode.INCORRECT_PAYMENT_AMOUNT, data=b'')
await self.fail_htlc(chan, htlc_id, onion_packet, reason) await self.fail_htlc(chan, htlc.htlc_id, onion_packet, reason)
return return
local_height = self.network.get_local_height() local_height = self.network.get_local_height()
if local_height + MIN_FINAL_CLTV_EXPIRY_ACCEPTED > cltv_expiry: if local_height + MIN_FINAL_CLTV_EXPIRY_ACCEPTED > htlc.cltv_expiry:
reason = OnionRoutingFailureMessage(code=OnionFailureCode.FINAL_EXPIRY_TOO_SOON, data=b'') reason = OnionRoutingFailureMessage(code=OnionFailureCode.FINAL_EXPIRY_TOO_SOON, data=b'')
await self.fail_htlc(chan, htlc_id, onion_packet, reason) await self.fail_htlc(chan, htlc.htlc_id, onion_packet, reason)
return return
cltv_from_onion = int.from_bytes(processed_onion.hop_data.per_hop.outgoing_cltv_value, byteorder="big") cltv_from_onion = int.from_bytes(processed_onion.hop_data.per_hop.outgoing_cltv_value, byteorder="big")
if cltv_from_onion != cltv_expiry: if cltv_from_onion != htlc.cltv_expiry:
reason = OnionRoutingFailureMessage(code=OnionFailureCode.FINAL_INCORRECT_CLTV_EXPIRY, reason = OnionRoutingFailureMessage(code=OnionFailureCode.FINAL_INCORRECT_CLTV_EXPIRY,
data=cltv_expiry.to_bytes(4, byteorder="big")) data=htlc.cltv_expiry.to_bytes(4, byteorder="big"))
await self.fail_htlc(chan, htlc_id, onion_packet, reason) await self.fail_htlc(chan, htlc.htlc_id, onion_packet, reason)
return return
amount_from_onion = int.from_bytes(processed_onion.hop_data.per_hop.amt_to_forward, byteorder="big") amount_from_onion = int.from_bytes(processed_onion.hop_data.per_hop.amt_to_forward, byteorder="big")
if amount_from_onion > amount_msat_htlc: if amount_from_onion > htlc.amount_msat:
reason = OnionRoutingFailureMessage(code=OnionFailureCode.FINAL_INCORRECT_HTLC_AMOUNT, reason = OnionRoutingFailureMessage(code=OnionFailureCode.FINAL_INCORRECT_HTLC_AMOUNT,
data=amount_msat_htlc.to_bytes(8, byteorder="big")) data=htlc.amount_msat.to_bytes(8, byteorder="big"))
await self.fail_htlc(chan, htlc_id, onion_packet, reason) await self.fail_htlc(chan, htlc.htlc_id, onion_packet, reason)
return return
self.network.trigger_callback('htlc_added', UpdateAddHtlc(**htlc, htlc_id=htlc_id), invoice, RECEIVED) self.network.trigger_callback('htlc_added', htlc, invoice, RECEIVED)
if self.network.config.debug_lightning_do_not_settle: if self.network.config.debug_lightning_do_not_settle:
return return
await self._fulfill_htlc(chan, htlc_id, preimage) await self._fulfill_htlc(chan, htlc.htlc_id, preimage)
async def _fulfill_htlc(self, chan: Channel, htlc_id: int, preimage: bytes): async def _fulfill_htlc(self, chan: Channel, htlc_id: int, preimage: bytes):
chan.settle_htlc(preimage, htlc_id) chan.settle_htlc(preimage, htlc_id)

17
electrum/lnutil.py

@ -567,8 +567,10 @@ class LnGlobalFeatures(IntFlag):
LN_GLOBAL_FEATURES_KNOWN_SET = set(LnGlobalFeatures) LN_GLOBAL_FEATURES_KNOWN_SET = set(LnGlobalFeatures)
class LNPeerAddr(namedtuple('LNPeerAddr', ['host', 'port', 'pubkey'])): class LNPeerAddr(NamedTuple):
__slots__ = () host: str
port: int
pubkey: bytes
def __str__(self): def __str__(self):
return '{}@{}:{}'.format(bh2u(self.pubkey), self.host, self.port) return '{}@{}:{}'.format(bh2u(self.pubkey), self.host, self.port)
@ -663,13 +665,14 @@ def format_short_channel_id(short_channel_id: Optional[bytes]):
+ 'x' + str(int.from_bytes(short_channel_id[3:6], 'big')) \ + 'x' + str(int.from_bytes(short_channel_id[3:6], 'big')) \
+ 'x' + str(int.from_bytes(short_channel_id[6:], 'big')) + 'x' + str(int.from_bytes(short_channel_id[6:], 'big'))
class UpdateAddHtlc(namedtuple('UpdateAddHtlc', ['amount_msat', 'payment_hash', 'cltv_expiry', 'htlc_id'])): class UpdateAddHtlc(namedtuple('UpdateAddHtlc', ['amount_msat', 'payment_hash', 'cltv_expiry', 'htlc_id'])):
""" # note: typing.NamedTuple cannot be used because we are overriding __new__
This whole class body is so that if you pass a hex-string as payment_hash,
it is decoded to bytes. Bytes can't be saved to disk, so we save hex-strings.
"""
__slots__ = () __slots__ = ()
def __new__(cls, *args, **kwargs): def __new__(cls, *args, **kwargs):
# if you pass a hex-string as payment_hash, it is decoded to bytes.
# Bytes can't be saved to disk, so we save hex-strings.
if len(args) > 0: if len(args) > 0:
args = list(args) args = list(args)
if type(args[1]) is str: if type(args[1]) is str:
@ -677,5 +680,7 @@ class UpdateAddHtlc(namedtuple('UpdateAddHtlc', ['amount_msat', 'payment_hash',
return super().__new__(cls, *args) return super().__new__(cls, *args)
if type(kwargs['payment_hash']) is str: if type(kwargs['payment_hash']) is str:
kwargs['payment_hash'] = bfh(kwargs['payment_hash']) kwargs['payment_hash'] = bfh(kwargs['payment_hash'])
if len(args) < 4 and 'htlc_id' not in kwargs:
kwargs['htlc_id'] = None
return super().__new__(cls, **kwargs) return super().__new__(cls, **kwargs)

26
electrum/tests/test_lnchannel.py

@ -207,13 +207,13 @@ class TestChannel(unittest.TestCase):
# First Alice adds the outgoing HTLC to her local channel's state # First Alice adds the outgoing HTLC to her local channel's state
# 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) self.aliceHtlcIndex = self.alice_channel.add_htlc(self.htlc_dict).htlc_id
self.assertNotEqual(self.alice_channel.hm.htlcs_by_direction(REMOTE, RECEIVED, 1), set()) self.assertNotEqual(self.alice_channel.hm.htlcs_by_direction(REMOTE, RECEIVED, 1), set())
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)
self.bobHtlcIndex = self.bob_channel.receive_htlc(self.htlc_dict) self.bobHtlcIndex = self.bob_channel.receive_htlc(self.htlc_dict).htlc_id
self.assertEqual(1, self.bob_channel.hm.log[LOCAL]['ctn'] + 1) self.assertEqual(1, self.bob_channel.hm.log[LOCAL]['ctn'] + 1)
self.assertNotEqual(self.bob_channel.hm.htlcs_by_direction(LOCAL, RECEIVED, 1), set()) self.assertNotEqual(self.bob_channel.hm.htlcs_by_direction(LOCAL, RECEIVED, 1), set())
@ -230,8 +230,8 @@ class TestChannel(unittest.TestCase):
def test_concurrent_reversed_payment(self): def test_concurrent_reversed_payment(self):
self.htlc_dict['payment_hash'] = bitcoin.sha256(32 * b'\x02') self.htlc_dict['payment_hash'] = bitcoin.sha256(32 * b'\x02')
self.htlc_dict['amount_msat'] += 1000 self.htlc_dict['amount_msat'] += 1000
bob_idx = self.bob_channel.add_htlc(self.htlc_dict) self.bob_channel.add_htlc(self.htlc_dict)
alice_idx = self.alice_channel.receive_htlc(self.htlc_dict) self.alice_channel.receive_htlc(self.htlc_dict)
self.alice_channel.receive_new_commitment(*self.bob_channel.sign_next_commitment()) self.alice_channel.receive_new_commitment(*self.bob_channel.sign_next_commitment())
self.assertEqual(len(self.alice_channel.pending_commitment(REMOTE).outputs()), 4) self.assertEqual(len(self.alice_channel.pending_commitment(REMOTE).outputs()), 4)
@ -481,8 +481,8 @@ class TestChannel(unittest.TestCase):
self.assertNotEqual(tx5, tx6) self.assertNotEqual(tx5, tx6)
self.htlc_dict['amount_msat'] *= 5 self.htlc_dict['amount_msat'] *= 5
bob_index = bob_channel.add_htlc(self.htlc_dict) bob_index = bob_channel.add_htlc(self.htlc_dict).htlc_id
alice_index = alice_channel.receive_htlc(self.htlc_dict) alice_index = alice_channel.receive_htlc(self.htlc_dict).htlc_id
bob_channel.pending_commitment(REMOTE) bob_channel.pending_commitment(REMOTE)
alice_channel.pending_commitment(LOCAL) alice_channel.pending_commitment(LOCAL)
@ -597,7 +597,7 @@ class TestChannel(unittest.TestCase):
def test_sign_commitment_is_pure(self): def test_sign_commitment_is_pure(self):
force_state_transition(self.alice_channel, self.bob_channel) force_state_transition(self.alice_channel, self.bob_channel)
self.htlc_dict['payment_hash'] = bitcoin.sha256(b'\x02' * 32) self.htlc_dict['payment_hash'] = bitcoin.sha256(b'\x02' * 32)
aliceHtlcIndex = self.alice_channel.add_htlc(self.htlc_dict) self.alice_channel.add_htlc(self.htlc_dict)
before_signing = self.alice_channel.to_save() before_signing = self.alice_channel.to_save()
self.alice_channel.sign_next_commitment() self.alice_channel.sign_next_commitment()
after_signing = self.alice_channel.to_save() after_signing = self.alice_channel.to_save()
@ -622,8 +622,8 @@ class TestAvailableToSpend(unittest.TestCase):
'cltv_expiry' : 5, 'cltv_expiry' : 5,
} }
alice_idx = alice_channel.add_htlc(htlc_dict) alice_idx = alice_channel.add_htlc(htlc_dict).htlc_id
bob_idx = bob_channel.receive_htlc(htlc_dict) bob_idx = bob_channel.receive_htlc(htlc_dict).htlc_id
force_state_transition(alice_channel, bob_channel) force_state_transition(alice_channel, bob_channel)
bob_channel.fail_htlc(bob_idx) bob_channel.fail_htlc(bob_idx)
alice_channel.receive_fail_htlc(alice_idx) alice_channel.receive_fail_htlc(alice_idx)
@ -745,8 +745,8 @@ class TestChanReserve(unittest.TestCase):
'amount_msat' : int(2 * one_bitcoin_in_msat), 'amount_msat' : int(2 * one_bitcoin_in_msat),
'cltv_expiry' : 5, 'cltv_expiry' : 5,
} }
alice_idx = self.alice_channel.add_htlc(htlc_dict) alice_idx = self.alice_channel.add_htlc(htlc_dict).htlc_id
bob_idx = self.bob_channel.receive_htlc(htlc_dict) bob_idx = self.bob_channel.receive_htlc(htlc_dict).htlc_id
force_state_transition(self.alice_channel, self.bob_channel) force_state_transition(self.alice_channel, self.bob_channel)
self.check_bals(one_bitcoin_in_msat*3\ self.check_bals(one_bitcoin_in_msat*3\
- self.alice_channel.pending_local_fee(), - self.alice_channel.pending_local_fee(),
@ -791,8 +791,8 @@ class TestDust(unittest.TestCase):
} }
old_values = [x.value for x in bob_channel.current_commitment(LOCAL).outputs() ] old_values = [x.value for x in bob_channel.current_commitment(LOCAL).outputs() ]
aliceHtlcIndex = alice_channel.add_htlc(htlc) aliceHtlcIndex = alice_channel.add_htlc(htlc).htlc_id
bobHtlcIndex = bob_channel.receive_htlc(htlc) bobHtlcIndex = bob_channel.receive_htlc(htlc).htlc_id
force_state_transition(alice_channel, bob_channel) force_state_transition(alice_channel, bob_channel)
alice_ctx = alice_channel.current_commitment(LOCAL) alice_ctx = alice_channel.current_commitment(LOCAL)
bob_ctx = bob_channel.current_commitment(LOCAL) bob_ctx = bob_channel.current_commitment(LOCAL)

Loading…
Cancel
Save