[Lightning-dev] A gossip network for cross-chain trampoline payments

Jorge Timón jtimon at jtimon.cc
Fri Nov 29 18:58:39 UTC 2019

I see more people are thinking about this cross-chain lightning problem and
even working on it, it seems.
That is great, let's please join forces if we can. I'm happy to help in any
way I can.

Here's an example on how I think things could work in the future, like 2 or
3 steps after what I think cdecker is doing and
like 5 or 6 steps of what I'm currently doing.
Please, point out anything I may be missing or any alternatives I'm not

Let's say Alice has a lightning node configured to run on network=chain_A.
She wants to pay an invoice Bob gave her, but it turns out that bob has his
lightning node configured for network=chain_B.

Let's assume we already have trampoline routing as per

In fact, let's copy the entire example there and change some things. We
part from:

Alice                 TA1                  TA2 -> TB3         Bob
  |                   ^ |                   ^      |           ^
  |                   | |                   |      |           |
  `---> H1 ---> H2 ---' `---> H3 ---> H4 ---'      `---> H5 ---'

But here not all nodes operate in the same chain, they distribute as

chain_A: Alice, TA1, TA2, H1, H2, H3, H4
chain_B: Bob, TB3, H5

Now the first problem we encounter, is that since TA2 and TB3 don't
operate in the same chain, the direct payment between them can't
happen as described in the example for regular trampoline payments,
for there can't be a channel between nodes in different chains.

But what if TA2 and TB3 belonged to the same person?
Let's call that person Carol and let's call the software that makes things
happen a "Gateway" (we can find a better name later, as with anything else).
Note that apart from TA2 and TB3, Carol's gateway could also connect to
other nodes operating in chain_C, chain_D and chain_E, for example.

Alice                 TA1                  TA2 -*?-> TB3         Bob
  |                   ^ |                   ^         |           ^
  |                   | |                   |         |           |
  `---> H1 ---> H2 ---' `---> H3 ---> H4 ---'         `---> H5 ---'

Now the main concern is to clarify what the "-*?->" nomenclature means.

But before that, shouldn't alice, when building trampoline_onion_packet,
notice that TB3 and Bob don't belong to chain_A?
We need a way for Alice to know that she can actually attempt that.
Carol could advertise that she is managing a gateway between TA2 and TB3
(perhaps more) in some gossip network.
Note this network doesn't need to be part of the lightning protocol, or be
just optional following the "it's ok to be odd" design.
Few things are easier than ignoring gossip that is not of your interest, I

We could have an update_gateway gossip message with something like:

- gateway_id
- list of node ids
- list of signatures by those node's ids
- signature by gateway_id

The proportional fees charged for different combinations may be different,
take into account that we're not only talking about fees but also prices,
for the asset in chain_A may not be the same as the asset in chain_B and,
even if they are,
there can be some discount for the units in one of the chains for whatever

Apart from a gossip message we would need some update_gateway_route,
perhaps with:

- src_chain_id
- dest_chain_id
- price (this can include an implicit proportional fee)

I know, this is a directed graph and it potentially grows exponentially
with the number of chains in the same gateway.
But it would be worse with a graph separately by node_id rather than
I honestly don't see other way around this.

Also, I know there's the "free option" problem (see
https://en.bitcoin.it/wiki/Atomic_swap#Financial_optionality ).
Let's remember that at the very moment Carol's gateway software is
processing "-*?->" some validation could be triggered
that concluded something along the lines:
"you know what? I don't like this H5 path nor any other I found for what I
consider a fair price at this very moment,
so I'm going to pass and forward back to whoever initiated this payment
an error saying I'm not ok with that price anymore, perhaps suggesting a
different one while at it.
I will also make sure my gateway nodes are sending the right price for that
pair and direction in update_gateway_route"

Well, that's not the best way to explain it but I think it can be
Even if that's not enough, even if other people can't find better ways to
mitigate the free option problem,
there are potential use cases with constant or relatively stable exchange
rates for which this shouldn't be a problem.
So let's please focus on everything else except for the free option problem
in this thread.

Let's just accept that both Alice and the gateway software are using some
formula to convert
from the amt_to_forward received by TA2 to the one that TB3 is supposed to
receive and process.
If f(amt_to_forward_TA2, price_current) > f(amt_to_forward_TA2,
TA2 may fail and send H4 an error that ultimately will get back to alice.
We could use amt_to_forward * price nomenclature rather than
f(amt_to_forward, price) if you like.
Let's just remember we need to define price's type though.
Presumably some approximation of rational numbers that computers can handle
reasonably well and
with a precision that is reasonable enough for our requirements.

Another operation that is required as part of "-*?->" (and that alice must
do) that I personally find much more troubling is the
calculation from amt_to_forward_TA2 to final_cltv_expiry for Bob or the
following outgoing_cltv_value if there were more trampoline nodes
inbetween, or even more gateways and chains.
With the price we can calculate f(amt_to_forward_AT2, price) =
amt_to_forward_BT3 and derive the rest from there,
even though a trampoline hop payload for TB3 is not needed since it can be
assumed by alice to be calculated by carol's gateway
from what it receives. The point is TB3 doesn't need to know or care about
the prices for other gateways after it.

Maybe I am mistaken, but just like with the price we should just be able to
define the following:

g(outgoing_cltv_value_TA2, chain_time_translation) = outgoing_cltv_value_TB2

So since Alice would need to calculate g too, in reality
update_gateway_route would look like:

- src_chain_id
- dest_chain_id
- price (this can include an implicit proportional fee)
- chain_time_translation

I imagine the type for chain_time_translation to be an imaginary number.
Actually, not. I usually imagine imaginary numbers as an array with 2 real
but in this case I think just 2 integers should be fine, sorry.
Why 2?
Well, chains not only have different start times and current height, they
also potentially have different
estimated times between blocks (ie bitcoin has 10 minutes, but other chains
have other settings).
I was I assuming something like:

g(outgoing_cltv_value_TA2, chain_time_translation) =
chain_time_translation_param_1 + (outgoing_cltv_value_TA2 *
chain_time_translation_param_2) =

Please anyone feel free to actually solve that problem before me.
I haven't thought hard about this because if I assume unity (1 as in
algebra class) for both price and chain_time_translation
I don't actually need to care about the types or the f and g operations,
since doing that I know f(x)=x and g(y)=y by definition if x=1 and y=1.

In any case, we know Alice (the payer) needs to calculate f and g for the
whole path using some inter-chain gossip. for prices and chain time

As part of "-*?->", Each gateway also should recalculate f and g locally,
potentially with different, more updated values of x and y and perhaps
return an error.

But beyond those 2 validations "-*?->" is pretty much undefined.

What I really want to define precisely in "-*?->" is how carol's gateway
(CG from now on) communicates with TA2 and TB3.

TA2 and TB3 have some kind of plugin or extension to talk to CG and also CG
can talk to them via rpc, cli or equivalent.
We can assume CG, TA2 and TB3 all run in the same machine or local network.

When TA2 receives a trampoline hop for which next's hop is a node in a list
of sibling gateway nodes configured on init or in the relevant plugin:

1) TA2 gives the peeled trampoline onion to CG (including the relevant
hmac) for it to process it and give an error back or:
2) CG gives the processed onion to TB3, which processes it even though it
perceives it as a loss, for it trusts any message from CG
3) Any errors received by TB3 must be relied back to TA2 through CG, that's
2 new messages for this mini-protocol within "-*?->"

If everything goes well, I think TB3 needs to communicate one more time
with TA2 through CG to pass the payment preimage.
But I'm not very sure about this part, I should re-read lightning-rfc more
If that's the case, there's 2 more messages here too (one from BT3 to TCG,
another from CG to TX2).

I feel the best way to document this communication between CG, TA2 and TB3
is a UML sequence diagram.
I promise one if people want it. I just need to reinstall plantUML, but I
won't do that today.

I hope people can find flaws on my assumptions or reasoning.
Or perhaps just add more detail to vaguely defined ideas.

Any form of feedback is welcomed.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.linuxfoundation.org/pipermail/lightning-dev/attachments/20191129/9e6c1842/attachment.html>

More information about the Lightning-dev mailing list