1
0

lnworker: introduce PaymentAttemptLog NamedTuple

This commit is contained in:
SomberNight
2019-12-10 03:17:57 +01:00
parent 24ebc77d76
commit b99add59c3
7 changed files with 76 additions and 39 deletions

View File

@@ -51,13 +51,13 @@ from .lnutil import (Outpoint, LNPeerAddr,
UnknownPaymentHash, MIN_FINAL_CLTV_EXPIRY_FOR_INVOICE,
NUM_MAX_EDGES_IN_PAYMENT_PATH, SENT, RECEIVED, HTLCOwner,
UpdateAddHtlc, Direction, LnLocalFeatures, format_short_channel_id,
ShortChannelID)
ShortChannelID, PaymentAttemptLog, PaymentAttemptFailureDetails)
from .lnutil import ln_dummy_address
from .transaction import PartialTxOutput, PartialTransaction, PartialTxInput
from .lnonion import OnionFailureCode
from .lnmsg import decode_msg
from .i18n import _
from .lnrouter import RouteEdge, is_route_sane_to_use
from .lnrouter import RouteEdge, LNPaymentRoute, is_route_sane_to_use
from .address_synchronizer import TX_HEIGHT_LOCAL
from . import lnsweep
from .lnwatcher import LNWatcher
@@ -118,7 +118,9 @@ class PaymentInfo(NamedTuple):
class NoPathFound(PaymentFailure):
pass
def __str__(self):
return _('No path found')
class LNWorker(Logger):
@@ -345,7 +347,7 @@ class LNWallet(LNWorker):
self.preimages = self.storage.get('lightning_preimages', {}) # RHASH -> preimage
self.sweep_address = wallet.get_receiving_address()
self.lock = threading.RLock()
self.logs = defaultdict(list)
self.logs = defaultdict(list) # type: Dict[str, List[PaymentAttemptLog]] # key is RHASH
# note: accessing channels (besides simple lookup) needs self.lock!
self.channels = {} # type: Dict[bytes, Channel]
@@ -891,7 +893,7 @@ class LNWallet(LNWorker):
return chan
@log_exceptions
async def _pay(self, invoice, amount_sat=None, attempts=1):
async def _pay(self, invoice, amount_sat=None, attempts=1) -> bool:
lnaddr = self._check_invoice(invoice, amount_sat)
payment_hash = lnaddr.paymenthash
key = payment_hash.hex()
@@ -905,23 +907,23 @@ class LNWallet(LNWorker):
self.save_payment_info(info)
self.wallet.set_label(key, lnaddr.get_description())
log = self.logs[key]
success = False
for i in range(attempts):
try:
route = await self._create_route_from_invoice(decoded_invoice=lnaddr)
except NoPathFound:
success = False
except NoPathFound as e:
log.append(PaymentAttemptLog(success=False, exception=e))
break
self.network.trigger_callback('invoice_status', key, PR_INFLIGHT)
success, preimage, failure_log = await self._pay_to_route(route, lnaddr)
payment_attempt_log = await self._pay_to_route(route, lnaddr)
log.append(payment_attempt_log)
success = payment_attempt_log.success
if success:
log.append((route, True, preimage))
break
else:
log.append((route, False, failure_log))
self.network.trigger_callback('invoice_status', key, PR_PAID if success else PR_FAILED)
return success
async def _pay_to_route(self, route, lnaddr):
async def _pay_to_route(self, route: LNPaymentRoute, lnaddr: LnAddr) -> PaymentAttemptLog:
short_channel_id = route[0].short_channel_id
chan = self.get_channel_by_short_id(short_channel_id)
if not chan:
@@ -948,8 +950,13 @@ class LNWallet(LNWorker):
self.logger.info("payment destination reported error")
else:
self.network.path_finder.add_to_blacklist(short_chan_id)
failure_log = (sender_idx, failure_msg, blacklist)
return success, preimage, failure_log
failure_log = PaymentAttemptFailureDetails(sender_idx=sender_idx,
failure_msg=failure_msg,
is_blacklisted=blacklist)
return PaymentAttemptLog(route=route,
success=success,
preimage=preimage,
failure_details=failure_log)
def handle_error_code_from_failed_htlc(self, failure_msg, sender_idx, route, peer):
code, data = failure_msg.code, failure_msg.data
@@ -1011,11 +1018,11 @@ class LNWallet(LNWorker):
f"min_final_cltv_expiry: {addr.get_min_final_cltv_expiry()}"))
return addr
async def _create_route_from_invoice(self, decoded_invoice) -> List[RouteEdge]:
async def _create_route_from_invoice(self, decoded_invoice) -> LNPaymentRoute:
amount_msat = int(decoded_invoice.amount * COIN * 1000)
invoice_pubkey = decoded_invoice.pubkey.serialize()
# use 'r' field from invoice
route = None # type: Optional[List[RouteEdge]]
route = None # type: Optional[LNPaymentRoute]
# only want 'r' tags
r_tags = list(filter(lambda x: x[0] == 'r', decoded_invoice.tags))
# strip the tag type, it's implicitly 'r' now