diff --git a/electrum/lnpeer.py b/electrum/lnpeer.py index 0c261f72b..399ddf470 100644 --- a/electrum/lnpeer.py +++ b/electrum/lnpeer.py @@ -1435,20 +1435,16 @@ class Peer(Logger): self.send_message("commitment_signed", channel_id=chan.channel_id, signature=sig_64, num_htlcs=len(htlc_sigs), htlc_signature=b"".join(htlc_sigs)) return True - def pay(self, *, + def create_onion_for_route( + self, *, route: 'LNPaymentRoute', - chan: Channel, amount_msat: int, total_msat: int, payment_hash: bytes, min_final_cltv_expiry: int, payment_secret: bytes, - trampoline_onion=None) -> UpdateAddHtlc: - - assert amount_msat > 0, "amount_msat is not greater zero" - assert len(route) > 0 - if not chan.can_send_update_add_htlc(): - raise PaymentFailure("Channel cannot send update_add_htlc") + trampoline_onion=None, + ): # add features learned during "init" for direct neighbour: route[0].node_features |= self.features local_height = self.network.get_local_height() @@ -1482,9 +1478,13 @@ class Peer(Logger): # create htlc if cltv > local_height + lnutil.NBLOCK_CLTV_EXPIRY_TOO_FAR_INTO_FUTURE: raise PaymentFailure(f"htlc expiry too far into future. (in {cltv-local_height} blocks)") + return onion, amount_msat, cltv, session_key + + def send_htlc(self, chan, payment_hash, amount_msat, cltv, onion, session_key=None) -> UpdateAddHtlc: htlc = UpdateAddHtlc(amount_msat=amount_msat, payment_hash=payment_hash, cltv_expiry=cltv, timestamp=int(time.time())) htlc = chan.add_htlc(htlc) - chan.set_onion_key(htlc.htlc_id, session_key) # should it be the outer onion secret? + if session_key: + chan.set_onion_key(htlc.htlc_id, session_key) # should it be the outer onion secret? self.logger.info(f"starting payment. htlc: {htlc}") self.send_message( "update_add_htlc", @@ -1497,6 +1497,33 @@ class Peer(Logger): self.maybe_send_commitment(chan) return htlc + def pay(self, *, + route: 'LNPaymentRoute', + chan: Channel, + amount_msat: int, + total_msat: int, + payment_hash: bytes, + min_final_cltv_expiry: int, + payment_secret: bytes, + trampoline_onion=None, + ) -> UpdateAddHtlc: + + assert amount_msat > 0, "amount_msat is not greater zero" + assert len(route) > 0 + if not chan.can_send_update_add_htlc(): + raise PaymentFailure("Channel cannot send update_add_htlc") + onion, amount_msat, cltv, session_key = self.create_onion_for_route( + route=route, + amount_msat=amount_msat, + total_msat=total_msat, + payment_hash=payment_hash, + min_final_cltv_expiry=min_final_cltv_expiry, + payment_secret=payment_secret, + trampoline_onion=trampoline_onion + ) + htlc = self.send_htlc(chan, payment_hash, amount_msat, cltv, onion, session_key=session_key) + return htlc + def send_revoke_and_ack(self, chan: Channel): self.logger.info(f'send_revoke_and_ack. chan {chan.short_channel_id}. ctn: {chan.get_oldest_unrevoked_ctn(LOCAL)}') rev = chan.revoke_current_commitment() @@ -1653,26 +1680,11 @@ class Peer(Logger): if next_peer is None: log_fail_reason(f"next_peer offline ({next_chan.node_id.hex()})") raise OnionRoutingFailure(code=OnionFailureCode.TEMPORARY_CHANNEL_FAILURE, data=outgoing_chan_upd_message) - next_htlc = UpdateAddHtlc( - amount_msat=next_amount_msat_htlc, - payment_hash=htlc.payment_hash, - cltv_expiry=next_cltv_expiry, - timestamp=int(time.time())) - next_htlc = next_chan.add_htlc(next_htlc) try: - next_peer.send_message( - "update_add_htlc", - channel_id=next_chan.channel_id, - id=next_htlc.htlc_id, - cltv_expiry=next_cltv_expiry, - amount_msat=next_amount_msat_htlc, - payment_hash=next_htlc.payment_hash, - onion_routing_packet=processed_onion.next_packet.to_bytes() - ) + next_htlc = next_peer.send_htlc(next_chan, htlc.payment_hash, next_amount_msat_htlc, next_cltv_expiry, processed_onion.next_packet) except BaseException as e: log_fail_reason(f"error sending message to next_peer={next_chan.node_id.hex()}") raise OnionRoutingFailure(code=OnionFailureCode.TEMPORARY_CHANNEL_FAILURE, data=outgoing_chan_upd_message) - next_peer.maybe_send_commitment(next_chan) return next_chan_scid, next_htlc.htlc_id @log_exceptions