<oembed><type>rich</type><version>1.0</version><author_name>npub1zlxd3xlzjhq2ue03e5m5p2w6mp8v3dkhq5r39flsftjjsje04wvsdd2k4w</author_name><author_url>https://nostr.ae/npub1zlxd3xlzjhq2ue03e5m5p2w6mp8v3dkhq5r39flsftjjsje04wvsdd2k4w</author_url><provider_name>njump</provider_name><provider_url>https://nostr.ae</provider_url><html>📅 Original date posted:2022-03-14&#xA;📝 Original message:&#xA;Dear Carsten, Martin and fellow lightning developers,&#xA;&#xA;first of all thank you very much for independently verifying and&#xA;acknowledging my recent findings about the runtime of finding a pieceweise&#xA;linearized approximation to the min cost flow problem, for working on&#xA;integrating them into lnd-manageJ and for your excellent questions &amp;&#xA;thoughts.&#xA;&#xA;On Sun, Mar 13, 2022 at 8:17 PM Carsten Otto via Lightning-dev &lt;&#xA;lightning-dev at lists.linuxfoundation.org&gt; wrote:&#xA;&#xA;&#xA;&gt; 1) What&#39;s the reasoning behind combining parallel channels?&#xA;&gt;&#xA;&#xA;Generally speaking this is pure pragmatism on my end to simplify my life as&#xA;handling parallel channels in some cases blows up complexity of code and&#xA;simulations. However I think from a probabilistic point of view ( see below&#xA;) the combination is more accurate to reflect the actual likelihood that&#xA;the liquidity is available.&#xA;&#xA;I agree that parallel channels make things a lot more complicated, but I&#xA;&gt; also see the benefit from a node operator&#39;s point of view. That being&#xA;&gt; said, wouldn&#39;t it suffice to treat parallel channels individually?&#xA;&gt;&#xA;&#xA;I think that should work and especially when including fees to the cost&#xA;function and considering how nodes handle routing requests on parallel&#xA;channels we might have to do so anyway. The suggested flows will probably&#xA;change in a way that disfavors parallel channels even if their virtual&#xA;capacity is larger than an alternative single channel (see below)&#xA;&#xA;1.1) A payment of size 2 needs to be split into 1+1 to fit through&#xA;&gt; parallel channels of size 1+1. Combining the 1+1 channels into a virtual&#xA;&gt; channel of size 2 only complicates the code that has to do come up with&#xA;&gt; a MPP that doesn&#39;t over-saturate the actual channels. On the other hand,&#xA;&gt; I don&#39;t think the probability for the virtual channel of size 2 is more&#xA;&gt; realistic than reasoning about two individual channels and their&#xA;&gt; probabilities - but I didn&#39;t even try to see the math behind that.&#xA;&gt; Please prove me wrong? :)&#xA;&gt;&#xA;&#xA;* The likelihood that a 1 Satoshi capacity channel has 1 Satoshi to route&#xA;is 1/2.&#xA;* The likelihood that 2 channels of capacity 1 have each 1 satoshi&#xA;available to route is 1/2*1/2 = 1/4&#xA;* Combining both parallel channels to one virtual channel of capacity 2 and&#xA;asking if 2 satoshis are available to route gives a likelihood of 1/3 which&#xA;is larger than 1/4.&#xA;&#xA;However I believe in practice one cannot just send a 2 satoshi onion and&#xA;expect the routing node to split the amount  correctly / accordingly&#xA;between the two parallel channels. (I might be wrong here). So in that case&#xA;modelling and computing probabilities for parallel channels might be&#xA;necessary anyway though the math indicates that splitting liquidity in&#xA;parallel channels will get you selected less frequently for routing.&#xA;&#xA;1.2) The Mission Control information provided by lnd can be used to&#xA;&gt; place a minimum available balance on each of the parallel channels. If&#xA;&gt; we know that node A isn&#39;t able to forward N sats to node B, we can treat&#xA;&gt; all parallel channels between A and B (in that direction) to have a&#xA;&gt; capacity of at most N-1 sats. How would this look like if we combined&#xA;&gt; the parallel channels into a virtual one? Note that it may still be&#xA;&gt; possible to route two individual payments/onions of size N-1 sats from A&#xA;&gt; to B, given two parallel channels with that many sats on A&#39;s side.&#xA;&gt;&#xA;&#xA;I think you talk a about a maximum available balance of a channel (and not&#xA;min available balance)?&#xA;In the case of parallel channels I am not even sure if such information is&#xA;accurate as it is my understanding that the routing node may decide to use&#xA;the parallel channel to forward the amount even though the other channel&#xA;was specified in the onion.&#xA;Assuming that routing nodes indeed do so we would have learnt that neither&#xA;channel has an effective capacity of N. So the combined virtual channel&#xA;could be seen as 2N-1. However if routing nodes don&#39;t locally split a&#xA;forwarding request across both channels we would know that calaculating&#xA;with 2N-1 is bad as a request of N could not be fulfilled. I guess it is&#xA;for the implementations that support parallel channels to figure out the&#xA;details here.&#xA;&#xA;2) Optimal Piecewise Linearization&#xA;&gt;&#xA;&gt; See Twitter [3].&#xA;&gt;&#xA;&gt; Is it worth it cutting a channel into pieces of different sizes, instead&#xA;&gt; of just having (as per your example) 5 pieces of the same size? If it&#xA;&gt; makes a noticeable difference, adding some complexity to the code might&#xA;&gt; be worth it.&#xA;&gt;&#xA;&#xA;I will certainly do experiments or be happy if others are faster to do them&#xA;which compare the quality of the approximation with optimal piecewise&#xA;linearization to my choice of fixed intervals and the selection of various&#xA;numbers of segments. As long as we don&#39;t have numbers it is hard to guess&#xA;if it is worthwhile adding the complexity. Looking at the current results&#xA;it seems that my (geometricly motivated but) arbitrary choice might end up&#xA;to be good and easy enough. However we might very well see quite an&#xA;improvement of the approximation if we find better piecewise linearizations.&#xA;&#xA;&#xA;&gt; 3) Size of Piecewise Linearization&#xA;&gt;&#xA;&gt; My gut feeling is that cutting a 1 BTC channel into 5 pieces is&#xA;&gt; different from cutting a 0.01 BTC channel into 5 pieces. Would it make&#xA;&gt; sense to use different values of N depending on the channel size?&#xA;&gt;&#xA;&#xA;The main difference here is that a channel of 1 BTC is highly preferable&#xA;from a probabilistic payment delivery perspective over a channel of 0.01&#xA;BTC. Even approximating the 1 BTC channel with 1000 intervalls of 0.001 BTC&#xA;should still have a lower unit cost in all pieces of the first 0.01 BTC of&#xA;the liquidity than the first piece of the 0.01 BTC channel. So I think&#xA;splitting all channels in the equal number of pieces is pretty well&#xA;motivated but let me elaborate on this:&#xA;&#xA;The motivation of splitting all channels into the same number of pieces&#xA;comes from the observation that from a probabilistic point of view (and&#xA;very roughly speaking!) we want to find a flow that puts the same (high)&#xA;success probability on all edges. Using 20% of the capacity gives an 80%&#xA;probability that the liquidity is available. This in turn has a 51.2%&#xA;chance to be successful on a three hop path which in my experience is a&#xA;good probability to aim for as on average one is expected to need two&#xA;attempts. Since the linearized pieces - if included in the flow - tend to&#xA;be fully saturated I decided that it makes sense to put them in 5 buckets&#xA;of 20% each. If you read the code carefully I don&#39;t even approximate the&#xA;cost correctly at the 2nd, 3rd, 4th and 5th piece. I just multiplied the&#xA;linearized unit cost of the first piece with 2,3,4 and 5 respectively Which&#xA;approximates the negative log probability with a quadratic cost function.&#xA;But as we can see those geometrically motivated choices work already pretty&#xA;well. Again I plan to invest more time to find a better approximation and&#xA;we might end up using it. But I don&#39;t expect too much gain from doing so.&#xA;&#xA; If you look at the output of the flow in the iPython notebook (Which I&#xA;will copy to the end of the mail for your convenience) you see that most&#xA;channels did not fully saturate the first piece and have a likelihood&#xA;between 80% and 100% where as some channels saturated the first piece&#xA;producing a likelihood of 80% and few channels saturated also the second&#xA;piece giving a likelihood of 60%.&#xA;&#xA;Thus I expect that the real value from studying the optimal piece wise&#xA;linear approximation will give us a better understanding of where to prune&#xA;segments away. If we note that in this flow not a single channel used the&#xA;third, forth and fifth piece we could have removed 60% of all edges and&#xA;doubled the runtime and still compute the same resulting flow.&#xA;&#xA;&#xA;&gt; 4) Leftovers after Piecewise Linearization&#xA;&gt;&#xA;&gt; If I cut some channel into N pieces, I might end up with up to N-1 sats&#xA;&gt; that don&#39;t end up in any of the N pieces, effectively making the channel&#xA;&gt; look smaller than it is. For smaller values of N that&#39;s obviously not an&#xA;&gt; issue (given the uncertainty we&#39;re dealing with), but it might be more&#xA;&gt; problematic if quantization is used with larger values. Any thoughts on&#xA;&gt; this?&#xA;&gt;&#xA;&#xA;I am not sure if I understand your question / issue here. The splitting&#xA;works by selecting N points on the domain of the function and splitting the&#xA;domain into segments at those points. This should never leave sats over.&#xA;The quantization which doesn&#39;t boost the runtime too much anyway happens&#xA;before piecewise linearization. So as long as the domain is larger than N&#xA;the piecewiese linearization should not bring up a situation where sats are&#xA;left over. If the quantization however makes a channel so small  that we&#xA;cannot even create 5 (or N) disjoint segments then I guess the likelihood&#xA;for being included into the final result is too small anyway. But I agree&#xA;that an actual implementation might have to watch out for such edge cases.&#xA;&#xA;Again this yield interesting pruning opportunities to reduce the seize of&#xA;the network before doing the expensive min cost flow computation. For&#xA;example I could prune channels with high unit costs on the first segment.&#xA;Especially if they are further away from the source and destination node.&#xA;This would overall reduce the size of the graph and improve runtime.&#xA;Already last July I had a pretty well working heurist that was able to&#xA;through away about 90% of all channels and would pretty much always find&#xA;the same flow in the pruned network as on the full network. I should really&#xA;prioritize the pruning work again now that we have fast solvers.&#xA;&#xA;5) Fees (and other properties?)&#xA;&gt;&#xA;&gt; How can we integrate fees into the function? I must admit, I haven&#39;t&#xA;&gt; even thought about that, yet. A copy-paste answer would be great,&#xA;&gt; though! :) Maybe it&#39;s also a good idea to punish channels based on their&#xA;&gt; CLTV delta? Ratio of enabled channels? Age? Manual punishment score? ...&#xA;&gt;&#xA;&#xA;plugging in fees (assuming only channels that set a base fee of zero) is&#xA;very easy and straight forward.&#xA;&#xA;Let&#39;s recall from the code that the piecewise linearized unit cost is&#xA;computed as follows&#xA;&#xA;unit_cost = int(max_cap/cap)for i in range(N):&#xA;     #arc format is src, dest, capacity, unit_cost&#xA;     arcs.append((src,dest,int(cap/(N*QUANTIZATION)),(i+1)*unit_cost))&#xA;&#xA;As described in our paper for a good (and to be determined) value of \mu we&#xA;could just create the linear combination between the two features which&#xA;would change the line to:&#xA;&#xA;     arcs.append((src,dest,int(cap/(N*QUANTIZATION)),(i+1)*unit_cost +&#xA;mu*fee_rate_ppm))&#xA;&#xA;Note two things:&#xA;1. the only requirement for the solver to work is that \mu*fee_rate_ppm&#xA;needs to be an integer. So in case \mu was smaller than 1 we could also&#xA;scale the term from the linearized log probabilities by putting a larger mu&#xA;to the feature arising from the cost of the uncertainty.&#xA;&#xA;     arcs.append((src,dest,int(cap/(N*QUANTIZATION)),mu*(i+1)*unit_cost&#xA;+ fee_rate_ppm))&#xA;&#xA;&#xA;2. the cost from the routing fees is the same on each segment of the&#xA;piecewise linearization which makes a lot of sense because the current&#xA;feerate is indeed a unit cost that does not change with how heavily you&#xA;plan to use a channel independently how the cost that comes from the&#xA;probability grows.&#xA;&#xA;With respect to other features I guess the entire topic of feature&#xA;engineering for our cost function should be a separate threat / topic and&#xA;line of research but as you asked I will give you some short thoughts on&#xA;this here:&#xA;&#xA;As pointed out to the c-lightning team in&#xA;https://github.com/ElementsProject/lightning/pull/4771#issuecomment-930173831&#xA;and&#xA;the following comment I believe that optimizing for CLTV is a poor choice&#xA;and in min cost flow computations it might very well be non linear anyway&#xA;and thus tricky to include in a meaningful way.Sure one could transform it&#xA;to a unit cost by doing something like CLTV*max_cap/cap and add it to the&#xA;cost function like the ppm. But I still do not really see why this is&#xA;useful. On the other hand I very much believe we should start to&#xA;investigate features that predict channel latency to setup / settle an HTLC&#xA;as suggested in the last paragraph of this comment&#xA;https://github.com/lightningdevkit/rust-lightning/issues/1170#issuecomment-972396747&#xA;However&#xA;I fear that latency measures again are non linear though they could again&#xA;be translated to a unit cost with the same trick as the CLTV.&#xA;&#xA;&#xA;&gt; 6) Non-Zero Base Fee&#xA;&gt;&#xA;&gt; See Twitter [4].&#xA;&gt;&#xA;&gt; According to Stefan [5] it should be possible to integrate ZmnSCPxj&#39;s ideas&#xA;&gt; to make this work with non-zero base fees. How?&#xA;&gt; Simpler approach: Twitter [6].&#xA;&gt;&#xA;&#xA;I don&#39;t have much to add to the base fee discussion at this point besides&#xA;the emphasize that the above described linearization trick for CLTV or&#xA;latency based features will not properly work for the base fee because one&#xA;actually has to pay the full base fee at the end - independently of how&#xA;much you saturate the channel. This might mess up the optimization.&#xA;&#xA;&#xA;&gt; 7) Private Channels&#xA;&gt;&#xA;&gt; [very niche topic, not really that interesting nor urgent]&#xA;&gt;&#xA;&gt; I&#39;m a fan of adding private channels to provide more outbound liquidity,&#xA;&gt; mainly to reduce gossip and hide my intentions. If my total liquidity to&#xA;&gt; some peer is below the amount announced in public channels, I don&#39;t see&#xA;&gt; any meaningful complication. However, I might have a public channel of&#xA;&gt; size N and several private channels bringing my local liquidity to some&#xA;&gt; value &gt;N. It&#39;s rather obvious that not announcing this fact is a bad&#xA;&gt; idea, as any #pickhardtpayments implementation would think I have 0-N on&#xA;&gt; my side of the channel(s). Assuming I&#39;m willing to accept this tradeoff,&#xA;&gt; do you see other complications or issues with hidden liquidity?&#xA;&gt;&#xA;&gt; My gut feeling is that this isn&#39;t an issue, at all, as channel balances&#xA;&gt; change all the time, which is something the algorithm already has to&#xA;&gt; deal with.&#xA;&gt;&#xA;&#xA;As you noted from a probabilistic payment delivery point of view I might be&#xA;interested in signaling all the liquidity that is being provided between&#xA;two peers and I shoot myself if I hide it. That being said you might have&#xA;reasons to do so and additionally I never rejected the idea to extend the&#xA;current probabilistic model with a probabilistic node or channel provenance&#xA;value that would be similar to the ideas in lnd&#39;s mission control or the&#xA;routescore by https://lnrouter.app. Given the fact that with hidden&#xA;liquidity the probabilities are constantly underestimated such a provenance&#xA;score will probably be higher than the one of other channels fixing the&#xA;&#34;introduced issue&#34; of hidden liquidity&#xA;&#xA;8) Quality of Approximation&#xA;&gt;&#xA;&gt; There are some problems in computer science that are hard/impossible to&#xA;&gt; approximate, in the sense that any kind of deviation from the optimum&#xA;&gt; could cause the computed results to be extremely bad. Do you have some&#xA;&gt; idea (or proof) that your kind of approximation isn&#39;t causing a major&#xA;&gt; issue? I guess a piece-wise linearization with an infinite number of&#xA;&gt; pieces corresponds to the optimal result. Given a finite number of&#xA;&gt; pieces, how large is the difference to the optimum?&#xA;&gt;&#xA;&#xA;We don&#39;t have to go to infinite to find a solution without error. We can&#xA;stay with the finite number that corresponds to the channels capacity and&#xA;make segments of 1 satoshi each encoding what this satoshi would actually&#xA;cost in the original function (assuming all values in the original function&#xA;were integers).&#xA;&#xA;I have not spent the time to properly express the error in dependence of&#xA;the number of segments N or even empirically study its tradeoffs in&#xA;practice (as I haven&#39;t even included the optimal piecewise linearization&#xA;yet) However the actual flow (see below) as well as the results from Dr.&#xA;Martin Berger&#xA;https://lists.linuxfoundation.org/pipermail/lightning-dev/2022-March/003513.html&#xA;indicate&#xA;that the error should be possible to be managed and stay small enough in&#xA;practice. That being said and as above it certainly makes sense to invest a&#xA;bit of time on how to conduct the piecewise linearization properly.&#xA;&#xA;Output of the computed flow from the iPython notebok with a piece wise&#xA;linearization of 5 equal sized segments per channel&#xA;&#xA;&#xA;Planning to deliver 0.50 BTC from 5051(03efccf...) to 13006&#xA;(021c97a...) via an approximated optimally reliable payment flow...&#xA;&#xA;Runtime of flow computation: 0.85 sec&#xA;Minimum approximated quadratic cost:  815932&#xA;&#xA; Arc &#x9;&#x9;&#x9;      Flow / Capacity &#x9;probability &#x9;Fee (sats)&#xA;5051 -&gt; 8463     &#x9;  6700000 / 16777215 &#x9;0.600649&#x9;8957.900000&#xA;5051 -&gt; 3437     &#x9;  1800000 / 9000000 &#x9;0.800000&#x9;2406.600000&#xA;5051 -&gt; 9162     &#x9;  1240000 / 6200000 &#x9;0.800000&#x9;1657.880000&#xA;5051 -&gt; 14746     &#x9;  6700000 / 16777215 &#x9;0.600649&#x9;8957.900000&#xA;5051 -&gt; 14832     &#x9;  2000000 / 10000000 &#x9;0.800000&#x9;2674.000000&#xA;6257 -&gt; 14832     &#x9;  3350000 / 2411344242 &#x9;0.998611&#x9;335.100000&#xA;14832 -&gt; 12446     &#x9;  5350000 / 6200000000 &#x9;0.999137&#x9;6.350000&#xA;7870 -&gt; 6257     &#x9;  3350000 / 20000000 &#x9;0.832500&#x9;34.500000&#xA;14746 -&gt; 12446     &#x9;  6700000 / 100000000 &#x9;0.933000&#x9;3350.000000&#xA;7914 -&gt; 13006     &#x9;  6700000 / 200000000 &#x9;0.966500&#x9;33501.000000&#xA;5051 -&gt; 550     &#x9;  3300000 / 15000000 &#x9;0.780000&#x9;4412.100000&#xA;11396 -&gt; 13192     &#x9;  6700000 / 1000000000 &#x9;0.993300&#x9;2010.000000&#xA;5051 -&gt; 11396     &#x9;  6700000 / 16777215 &#x9;0.600649&#x9;8957.900000&#xA;7199 -&gt; 9162     &#x9;  3350000 / 445000000 &#x9;0.992472&#x9;848.550000&#xA;9162 -&gt; 12446     &#x9;  16590000 / 3900000000 &#x9;0.995746&#x9;17.590000&#xA;5051 -&gt; 13287     &#x9;  2000000 / 10000000 &#x9;0.800000&#x9;2674.000000&#xA;5051 -&gt; 1843     &#x9;  6700000 / 16777215 &#x9;0.600649&#x9;8957.900000&#xA;5051 -&gt; 11257     &#x9;  3350000 / 16777215 &#x9;0.800324&#x9;4478.950000&#xA;1953 -&gt; 12446     &#x9;  2160000 / 750000000 &#x9;0.997120&#x9;1080.000000&#xA;550 -&gt; 1843     &#x9;  3300000 / 30000000 &#x9;0.890000&#x9;1155.000000&#xA;12756 -&gt; 12446     &#x9;  2000000 / 16775679 &#x9;0.880780&#x9;301.000000&#xA;5051 -&gt; 12756     &#x9;  2000000 / 10000000 &#x9;0.800000&#x9;2674.000000&#xA;3437 -&gt; 12446     &#x9;  1800000 / 400000000 &#x9;0.995500&#x9;225.001000&#xA;6713 -&gt; 7914     &#x9;  6700000 / 200000000 &#x9;0.966500&#x9;837.501000&#xA;11257 -&gt; 7199     &#x9;  3350000 / 16777215 &#x9;0.800324&#x9;663.300000&#xA;10914 -&gt; 9162     &#x9;  2000000 / 500000000 &#x9;0.996000&#x9;1000.001000&#xA;5051 -&gt; 7870     &#x9;  3350000 / 16777215 &#x9;0.800324&#x9;3.781000&#xA;8463 -&gt; 5288     &#x9;  6700000 / 500000000 &#x9;0.986600&#x9;837.501000&#xA;2781 -&gt; 10914     &#x9;  2000000 / 500000000 &#x9;0.996000&#x9;401.000000&#xA;13192 -&gt; 6713     &#x9;  6700000 / 500000000 &#x9;0.986600&#x9;16750.000000&#xA;32 -&gt; 2781     &#x9;  2000000 / 210000000 &#x9;0.990476&#x9;200.000000&#xA;5051 -&gt; 9530     &#x9;  2160000 / 10811137 &#x9;0.800206&#x9;2.591000&#xA;9530 -&gt; 1953     &#x9;  2160000 / 16777215 &#x9;0.871254&#x9;438.336000&#xA;1843 -&gt; 9162     &#x9;  10000000 / 300000000 &#x9;0.966667&#x9;2500.000000&#xA;5051 -&gt; 14642     &#x9;  2000000 / 10000000 &#x9;0.800000&#x9;2.431000&#xA;14642 -&gt; 13006     &#x9;  2000000 / 50000000 &#x9;0.960000&#x9;6001.000000&#xA;13287 -&gt; 32     &#x9;  2000000 / 16777215 &#x9;0.880791&#x9;500.000000&#xA;12446 -&gt; 13006     &#x9;  34600000 / 200000000 &#x9;0.827000&#x9;103766.400000&#xA;5288 -&gt; 13006     &#x9;  6700000 / 100000000 &#x9;0.933000&#x9;15216.700000&#xA;&#xA;Probability of entire flow: 0.0032&#xA;Total fee: 248793.763 sats&#xA;Effective fee rate: 0.498 %&#xA;Arcs included in payment flow: 39&#xA;&#xA;Don&#39;t get confused by a low probability. The first attampt always has&#xA;high uncertainty. We will learn fast in each consequitive round.&#xA;&#xA;&#xA;With kind regards Rene Pickhardt&#xA;&#xA;-- &#xA;&gt; Dr. Carsten Otto&#xA;&gt; carsten at c-otto.de&#xA;&gt; https://c-otto.de&#xA;&gt; _______________________________________________&#xA;&gt; Lightning-dev mailing list&#xA;&gt; Lightning-dev at lists.linuxfoundation.org&#xA;&gt; https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev&#xA;&gt;&#xA;&#xA;&#xA;-- &#xA;https://www.rene-pickhardt.de&#xA;-------------- next part --------------&#xA;An HTML attachment was scrubbed...&#xA;URL: &lt;http://lists.linuxfoundation.org/pipermail/lightning-dev/attachments/20220314/77da14bd/attachment-0001.html&gt;</html></oembed>