Merge pull request #10325 from f321x/debug_not_enough_balance
lightning: fix race when doing concurrent payments
This commit is contained in:
@@ -914,6 +914,7 @@ class LNWallet(LNWorker):
|
|||||||
self._paysessions = dict() # type: Dict[bytes, PaySession]
|
self._paysessions = dict() # type: Dict[bytes, PaySession]
|
||||||
self.sent_htlcs_info = dict() # type: Dict[SentHtlcKey, SentHtlcInfo]
|
self.sent_htlcs_info = dict() # type: Dict[SentHtlcKey, SentHtlcInfo]
|
||||||
self.received_mpp_htlcs = self.db.get_dict('received_mpp_htlcs') # type: Dict[str, ReceivedMPPStatus] # payment_key -> ReceivedMPPStatus
|
self.received_mpp_htlcs = self.db.get_dict('received_mpp_htlcs') # type: Dict[str, ReceivedMPPStatus] # payment_key -> ReceivedMPPStatus
|
||||||
|
self._channel_sending_capacity_lock = asyncio.Lock()
|
||||||
|
|
||||||
# detect inflight payments
|
# detect inflight payments
|
||||||
self.inflight_payments = set() # (not persisted) keys of invoices that are in PR_INFLIGHT state
|
self.inflight_payments = set() # (not persisted) keys of invoices that are in PR_INFLIGHT state
|
||||||
@@ -1698,10 +1699,16 @@ class LNWallet(LNWorker):
|
|||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
if (amount_to_send := paysession.get_outstanding_amount_to_send()) > 0:
|
if (amount_to_send := paysession.get_outstanding_amount_to_send()) > 0:
|
||||||
|
remaining_fee_budget_msat = (budget.fee_msat * amount_to_send) // amount_to_pay
|
||||||
|
# splitting the amount of the payment between our channels requires the correct
|
||||||
|
# available channel balance. to prevent concurrent splitting attempts from
|
||||||
|
# using stale channel balances for the split calculation a lock needs to be
|
||||||
|
# taken until the htlcs are added to the channel so the next splitting attempt
|
||||||
|
# acts on a correct channel balance.
|
||||||
|
async with self._channel_sending_capacity_lock:
|
||||||
# 1. create a set of routes for remaining amount.
|
# 1. create a set of routes for remaining amount.
|
||||||
# note: path-finding runs in a separate thread so that we don't block the asyncio loop
|
# note: path-finding runs in a separate thread so that we don't block the asyncio loop
|
||||||
# graph updates might occur during the computation
|
# graph updates might occur during the computation
|
||||||
remaining_fee_budget_msat = (budget.fee_msat * amount_to_send) // amount_to_pay
|
|
||||||
routes = self.create_routes_for_payment(
|
routes = self.create_routes_for_payment(
|
||||||
paysession=paysession,
|
paysession=paysession,
|
||||||
amount_msat=amount_to_send,
|
amount_msat=amount_to_send,
|
||||||
|
|||||||
@@ -218,6 +218,7 @@ class MockLNWallet(Logger, EventListener, NetworkRetryManager[LNPeerAddr]):
|
|||||||
self._payment_bundles_pkey_to_canon = {} # type: Dict[bytes, bytes]
|
self._payment_bundles_pkey_to_canon = {} # type: Dict[bytes, bytes]
|
||||||
self._payment_bundles_canon_to_pkeylist = {} # type: Dict[bytes, Sequence[bytes]]
|
self._payment_bundles_canon_to_pkeylist = {} # type: Dict[bytes, Sequence[bytes]]
|
||||||
self.config.INITIAL_TRAMPOLINE_FEE_LEVEL = 0
|
self.config.INITIAL_TRAMPOLINE_FEE_LEVEL = 0
|
||||||
|
self._channel_sending_capacity_lock = asyncio.Lock()
|
||||||
|
|
||||||
self.logger.info(f"created LNWallet[{name}] with nodeID={local_keypair.pubkey.hex()}")
|
self.logger.info(f"created LNWallet[{name}] with nodeID={local_keypair.pubkey.hex()}")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user