lnpeer.maybe_fulfill_htlc: follow BOLTs re some errors
related: https://github.com/lightningnetwork/lightning-rfc/pull/608
This commit is contained in:
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user