Browse Source

lnpeer.maybe_fulfill_htlc: follow BOLTs re some errors

related: https://github.com/lightningnetwork/lightning-rfc/pull/608
patch-4
SomberNight 4 years ago
parent
commit
31bdb5c344
No known key found for this signature in database GPG Key ID: B33B5F232C6271E9
  1. 29
      electrum/lnpeer.py

29
electrum/lnpeer.py

@ -1507,13 +1507,21 @@ class Peer(Logger):
asyncio.ensure_future(forward_trampoline_payment()) asyncio.ensure_future(forward_trampoline_payment())
def maybe_fulfill_htlc( def maybe_fulfill_htlc(
self, *, self, *,
chan: Channel, chan: Channel,
htlc: UpdateAddHtlc, htlc: UpdateAddHtlc,
processed_onion: ProcessedOnionPacket, processed_onion: ProcessedOnionPacket,
is_trampoline:bool = False) -> Optional[bytes]: is_trampoline: bool = False,
) -> Optional[bytes]:
"""As a final recipient of an HTLC, decide if we should fulfill it.
Returns the preimage if yes, or None.
"""
try:
amt_to_forward = processed_onion.hop_data.payload["amt_to_forward"]["amt_to_forward"]
except:
raise OnionRoutingFailure(code=OnionFailureCode.INVALID_ONION_PAYLOAD, data=b'\x00\x00\x00')
# Check that our blockchain tip is sufficiently recent so that we have an approx idea of the height. # Check that our blockchain tip is sufficiently recent so that we have an approx idea of the height.
# We should not release the preimage for an HTLC that its sender could already time out as # We should not release the preimage for an HTLC that its sender could already time out as
@ -1522,8 +1530,11 @@ class Peer(Logger):
if chain.is_tip_stale(): if chain.is_tip_stale():
raise OnionRoutingFailure(code=OnionFailureCode.TEMPORARY_NODE_FAILURE, data=b'') raise OnionRoutingFailure(code=OnionFailureCode.TEMPORARY_NODE_FAILURE, data=b'')
local_height = chain.height() local_height = chain.height()
exc_incorrect_or_unknown_pd = OnionRoutingFailure(
code=OnionFailureCode.INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS,
data=amt_to_forward.to_bytes(8, byteorder="big") + local_height.to_bytes(4, byteorder="big"))
if local_height + MIN_FINAL_CLTV_EXPIRY_ACCEPTED > htlc.cltv_expiry: if local_height + MIN_FINAL_CLTV_EXPIRY_ACCEPTED > htlc.cltv_expiry:
raise OnionRoutingFailure(code=OnionFailureCode.FINAL_EXPIRY_TOO_SOON, data=b'') raise exc_incorrect_or_unknown_pd
try: try:
cltv_from_onion = processed_onion.hop_data.payload["outgoing_cltv_value"]["outgoing_cltv_value"] cltv_from_onion = processed_onion.hop_data.payload["outgoing_cltv_value"]["outgoing_cltv_value"]
except: except:
@ -1534,10 +1545,6 @@ class Peer(Logger):
raise OnionRoutingFailure( raise OnionRoutingFailure(
code=OnionFailureCode.FINAL_INCORRECT_CLTV_EXPIRY, code=OnionFailureCode.FINAL_INCORRECT_CLTV_EXPIRY,
data=htlc.cltv_expiry.to_bytes(4, byteorder="big")) data=htlc.cltv_expiry.to_bytes(4, byteorder="big"))
try:
amt_to_forward = processed_onion.hop_data.payload["amt_to_forward"]["amt_to_forward"]
except:
raise OnionRoutingFailure(code=OnionFailureCode.INVALID_ONION_PAYLOAD, data=b'\x00\x00\x00')
try: try:
total_msat = processed_onion.hop_data.payload["payment_data"]["total_msat"] total_msat = processed_onion.hop_data.payload["payment_data"]["total_msat"]
except: except:
@ -1554,21 +1561,21 @@ class Peer(Logger):
info = self.lnworker.get_payment_info(htlc.payment_hash) info = self.lnworker.get_payment_info(htlc.payment_hash)
if info is None: if info is None:
raise OnionRoutingFailure(code=OnionFailureCode.INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS, data=b'') raise exc_incorrect_or_unknown_pd
preimage = self.lnworker.get_preimage(htlc.payment_hash) preimage = self.lnworker.get_preimage(htlc.payment_hash)
try: try:
payment_secret_from_onion = processed_onion.hop_data.payload["payment_data"]["payment_secret"] payment_secret_from_onion = processed_onion.hop_data.payload["payment_data"]["payment_secret"]
except: except:
if total_msat > amt_to_forward: if total_msat > amt_to_forward:
# payment_secret is required for MPP # payment_secret is required for MPP
raise OnionRoutingFailure(code=OnionFailureCode.INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS, data=b'') raise exc_incorrect_or_unknown_pd
# TODO fail here if invoice has set PAYMENT_SECRET_REQ # TODO fail here if invoice has set PAYMENT_SECRET_REQ
else: else:
if payment_secret_from_onion != derive_payment_secret_from_payment_preimage(preimage): if payment_secret_from_onion != derive_payment_secret_from_payment_preimage(preimage):
raise OnionRoutingFailure(code=OnionFailureCode.INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS, data=b'') raise exc_incorrect_or_unknown_pd
invoice_msat = info.amount_msat invoice_msat = info.amount_msat
if not (invoice_msat is None or invoice_msat <= total_msat <= 2 * invoice_msat): if not (invoice_msat is None or invoice_msat <= total_msat <= 2 * invoice_msat):
raise OnionRoutingFailure(code=OnionFailureCode.INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS, data=b'') raise exc_incorrect_or_unknown_pd
accepted, expired = self.lnworker.htlc_received(chan.short_channel_id, htlc, total_msat) accepted, expired = self.lnworker.htlc_received(chan.short_channel_id, htlc, total_msat)
if accepted: if accepted:
return preimage return preimage

Loading…
Cancel
Save