- all forwarding types use the same flow
- forwarding callback returns a htlc_key or None
- forwarding info is persisted in lnworker:
- ongoing_forwardings
- downstream to upstream htlc_key
- htlc_key -> error_bytes
- a node scid alias is derived from the node ID
- the channel opening fee is sent in a TLV field of open_channel
- the server requires htlc settlement before broadcasting
(server does not trust client)
- introduce PaymentFeeBudget, which contains limits for fee budget and cltv budget
- when splitting a payment,
- the fee budget is linearly distributed between the parts
- this resolves a FIXME in lnrouter ("FIXME in case of MPP")
- the cltv budget is simply copied
- we could also add other kinds of budgets later, e.g. for the num in-flight htlcs
- resolves TODO in lnworker ("todo: compare to the fee of the actual route we found")
- is_trampoline was True iff we are the final recipient of a trampoline payment
- in that case, we were only comparing htlc.cltv_expiry against the outer onion cltv
- we should and do now also compare against the inner onion cltv
- the checks are changed from "!=" to "<", to adapt to bolts PR 1032
- see b38156b951
- note that the leniency is needed for the cltv off-by-one
added in eca10eb04d to work
propageate back to the sender.
lnworker: in htlc_fulfilled and htlc_failed, return early if the
htlc was forwarded, so that we do not trigger invoice callbacks
lnworker.pay_to_node(min_cltv_expiry=) expects a relative cltv, and
we were passing an absolute one.
It is not so clear what precisely should be passed here, and that is
because pay_to_node's API was not written with forwarding in mind.
The value chosen here is just some guess that typically should work.
- construct_channel_announcement: return also whether
node ids are in reverse order
- maybe_send_channel_announcement:
return early if signatures have not been received
- partial writes are append only.
- StoredDict objects will append partial writes to the wallet
file when items are added, replaced, removed.
- Lists in the wallet file that have not been registered
as StoredObject are converted to StoredList, which
overloads append() and remove(). Those methods too will
append partial writes to the wallet file.
- Unlike the old jsonpatch branch, this branch does not support
file encryption. Encrypted files always fully rewritten, even
if the change before encryption is a partial write.
Somewhat a follow-up to 649ce979ab.
This adds some safety belts so we don't accidentally sign a tx that
contains a dummy address.
Specifically we check that tx does not contain output for dummy addr:
- in wallet.sign_transaction
- in network.broadcast_transaction
The second one is perhaps redundant, but I think it does not hurt.
Due to an indendation error, fw_info was returned only for one
HTLC of the MPP. Thus, maybe_fulfill_htlc was called again with
the remaining HTLCs, which could possibly be failed due to MPP
timeout, resulting in fund loss for the forwarder.
- rename trampoline_forwardings -> final_onion_forwardings,
because this dict is used for both trampoline and hold invoices
- remove timeout from hold_invoice_callbacks (redundant with invoice)
- add test_failure boolean parameter to TestPeer._test_simple_payment,
in order to test correct propagation of OnionRoutingFailures.
- maybe_fulfill_htlc: raise an OnionRoutingFailure if we do not have
the preimage for a payment that does not have a hold invoice callback.
Without this, the above unit tests stall when we use test_failure=True
- introduce SentHtlcInfo named tuple
- some previously unnamed tuples are now much shorter:
create_routes_for_payment no longer returns an 8-tuple!
- sent_htlcs_q (renamed from sent_htlcs), is now keyed on payment_hash+payment_secret
(needed for proper trampoline forwarding)
- add RecvMPPResolution enum for possible states of a pending incoming MPP,
and use it in check_mpp_status
- new state: "FAILED", to allow nicely failing back the whole MPP set
- key more things with payment_hash+payment_secret, for consistency
(just payment_hash is insufficient for trampoline forwarding)
triggered a payment forwarding.
Final onions may trigger a payment forwarding, through the callback
returned by maybe_fulfill_htlc. In that case, we should not fail the
HTLC later; doing so might result in fund loss.
Remove test_simple_payment_with_hold_invoice_timing_out: once we
have accepted to forward a payment HTLC with a hold invoice, we
do not want to time it out, for the same reason.
- maybe_fulfill_htlc returns a forwarding callback that
covers both cases.
- previously, the callback of hold invoices was called as a
side-effect of lnworker.check_mpp_status.
- the same data structures (lnworker.trampoline_forwardings,
lnworker.trampoline_forwarding_errors) are used for both
trampoline forwardings and hold invoices.
- maybe_fulfill_htlc still recursively calls itself to perform
checks on trampoline onion. This is ugly, but ugliness is now
contained to that method.
- fix parameters passed to maybe_forward_trampoline
- use lnworker.trampoline_forwardings as a semaphore for ongoing
trampoline payments
- if a trampoline payment fails, fail all received HTLCs