Open artemii235 opened 2 years ago
LDK/Rust-Lightning is the only good rust lightning network library/crate that exists, there are other libraries that implement LN in Rust but only partially. It also states in the about section that it's designed for integrating lightning with custom features such as our own chain sync/key management/data storage/backup logic.
Update on whether HTLCs are possible on LN. HTLCs are native to the lightning network as they enable payments between 2 lightning addresses that don't have a direct payment channel open between them. this is done through trustless routing of HTLC payments via a network of channels to open a path for payment between the 2 addresses. Also, atomic swaps between lightning network and on-chain blockchain addresses already exist and are called submarine swaps. Submarine swaps are mainly used to fund lightning payment channels directly with BTC instead of closing and opening the channel with more funds which cost more in transaction fees. The submarine swaps concept can be extended to swap lightning BTC with other chains and has been implemented before with LTC and BCH.
A few Issues we should take into consideration when Integrating lightning to mm2.
In lightning, the parties involved in a transaction must be online during the transaction to prevent fraudulent behavior. If a party goes offline for an extended period of time for any reason an execution fork attack can be carried out. An execution fork can revert a payment channel’s history, potentially causing financial damage to a party that is innocent except for having crashed. To mitigate this watchtowers have been proposed. Watchtowers are third-party services that enable such parties to delegate the cancelation of execution forks on their behalf. I think we should have our own watchtower server/service to prevent such attacks when a user of mm2 goes offline for whatever reason while using the lightning network for a swap.
Another issue that is also solved by third-party services is channel capacity. Presumably when a swap using LN and another chain needs to occur both the sender and the receiver need to open a channel (BTC multisig wallet) between them. Opening a channel is costly since it involves an on-chain transaction. This is solved by using multihop payments which involves forwarding payments through channels that already exist if a route can be found between the sender and the receiver. But the problem is that the amount that can be sent is capped by the minimum amount available between the hops that the payment can be routed through, this is where the third-party service comes into play as they provide a channel with big capacity that LN users can open a channel with and can find each other through it. I don't know if we can provide such service or if we integrate with such services so that when an mm2 user opens a lightning channel for the first time uses it providing easy routes for all mm2 users otherwise swaps on LN can be capped to very low amounts.
The last issue is not really an issue but a proposal of how to chose between transacting BTC on LN or on-chain. The lightning network fees grow linearly with the amount transacted, so LN swaps are perfect for small swaps. But if the amount is big enough the on-chain transaction fees can be lower than LN fees, this is not taking transaction speed into consideration of course as LN transactions are a lot faster. So when implementing LN fees in mm2 in the future we should take this into consideration.
@artemii235 The next step will be to implement an HTLC PoC on the testnet following this example https://github.com/KomodoPlatform/atomicDEX-API/blob/mm2.1/mm2src/coins/eth/eth_tests.rs#L196 as we discussed.
The following is the best technical book on the lightning network (Maybe the only one) https://github.com/lnbook/lnbook it's equivalent to the "Programming Bitcoin" book but for LN. It's not officially released yet but should be in Jan of 2022. They released the work on progress and now the final production version on Github.
We should consider researching the Joule in regards to Lightning web wallet support: https://lightningjoule.com/ https://github.com/joule-labs/joule-extension cc @ca333 @tonymorony
Just opened the lightning payments PR.
After the review process and merging to dev, the next step should be persisting lightning payments and channels history (closed channels) to storage (SQLite) and implementing channels monitors external backup.
Payments history is analogous to transactions history for other coins, as for monitors backup, this is required because lightning channels can't be reconstructed from the seed only unlike other coins so backup to external drive or cloud services is required.
Once both of these functionalities are implemented minimal lightning wallet functionalities can be considered ready.
I updated the above checklist with the upcoming steps. The ordering of these steps can be changed based on priorities.
After a swap P.O.C with lightning coin as taker was implemented, the next step would be to implement locktimes correctly for lightning. This will let us continue the implementation of maker swaps and swaps refunds for lightning coin. Here are some notes on my research about how swap locktimes can be implemented for lightning:
cltv_expiry_delta
in the HTLC is chosen to give the receiving party a window to spend the first path using the preimage.cltv_expiry_delta
was chosen to be large enough (at least 34 blocks) to give the routing parties the chance to appear back online and claim the payment on-chain if the channel between them was closed.
cltv_expiry_delta
is negotiated by the counterparties when opening a channel between them and remains the same value unless the channel is updated. If the channel was updated, the HTLCs in the commitment transactions are not updated with new locktime values of course. Only new HTLCs for new payments use the new value.cltv_expiry_delta
:
cltv_expiry_delta
of 40 blocks. We can call this value MEDIAN_HOP_CLTV_EXPIRY_DELTA
. This is the value that will be used in all the assumptions to calculate a safe locktime for swap payments.cltv_expiry_delta
value for channels opened with rust-lightning is 42 blocks.MEDIAN_HOP_CLTV_EXPIRY_DELTA
is the locktime for only 1 hop:
cltv_expiry_delta
that is equal to the MEDIAN_HOP_CLTV_EXPIRY_DELTA
final_cltv_expiry
. final_cltv_expiry
must be greater than a value determined by the receiving node in the invoice. This value is called min_final_cltv_expiry
.min_final_cltv_expiry
has a minimum allowed value of 24 blocks in rust-lightning. This is the value that is currently used in swaps implementations.final_cltv_expiry
is increased by a random value to obfuscate who is receiving this payment to the routing nodes, this is required since lightning payments should be private. This obfuscating is done by a concept called shadow routing, this consists of adding a cltv value of a random chosen real route after the last hop consisting of 1 to 3 more hops.final_cltv_expiry = min_final_cltv_expiry + shadow_route_cltv_expiry
or for the maximum value that we will use for swap locktimes calculations is min_final_cltv_expiry + 3 * MEDIAN_HOP_CLTV_EXPIRY_DELTA
median_total_cltv_expiry = (no_of_hops + 3) * MEDIAN_HOP_CLTV_EXPIRY_DELTA + min_final_cltv_expiry
median_total_cltv_expiry
for the taker payment will be 264 blocks
. This means that the maker payment in the other coin should have a locktime of 528 blocks
which is about 3 days and 16 hours
. If something goes wrong in the swap the maker will need a lot of time to refund his payment, by reducing the number of hops for swap payments to 3 we reduce the probability of the lightning payment swap to fail too. We can reduce the maker locktime by not making it double the taker locktime in this case but I am not sure if this is the right call. What do you think @artemii235?
min_final_cltv_expiry
which should be double the taker payment locktime.@shamardy Thanks for very detailed research! 🙂
The median_total_cltv_expiry for the maker payment will also be 264 blocks. In this case the taker swap locktime will be 22 hours. I believe this is acceptable.
Yes, this seems acceptable. Though,
This means that the maker payment in the other coin should have a locktime of 528 blocks which is about 3 days and 16 hours.
is a bit too much 🙂
We can reduce the maker locktime by not making it double the taker locktime in this case but I am not sure if this is the right call.
We can try it - with such a long lock duration, even 1,5x will give taker enough time to act even if his payment is spent right before locktime expiration.
Also, a couple of questions:
examples demonstrate the node having cltv_expiry_delta=10
. Why rust-lightning uses 42
as default value and why it can't be decreased? Lowering it to minimum recommended 34 value could give us a noticeable outcome.
(no_of_hops + 3)
- I couldn't find an explanation on why 3 is added to number of hops? 🙂 Can this constant be decreased?
The median_total_cltv_expiry for the maker payment will also be 264 blocks. In this case the taker swap locktime will be 22 hours. I believe this is acceptable.
Yes, this seems acceptable. Though,
First, Just adding a note about this to not forget :)
The taker has to make sure that the final_cltv_expiry
(last hop cltv) for the maker lightning payment is at least double his (other coin) swap locktime. I will add this info to the above research comment to have a complete picture in one comment.
(no_of_hops + 3) - I couldn't find an explanation on why 3 is added to number of hops? 🙂 Can this constant be decreased?
The 3 is related to the maximum shadow route hops. As shown by the below quote from the my original comment.
The final_cltv_expiry is increased by a random value to obfuscate who is receiving this payment to the routing nodes, this is required since lightning payments should be private. This obfuscating is done by a concept called shadow routing, this consists of adding a cltv value of a random chosen real route after the last hop consisting of 1 to 3 more hops.
I believe it can be decreased, or even be zero
in some cases :)
The max_total_cltv_expiry_delta
that can be specified in the route parameters when finding a route for the payment can be set to a value of no_of_hops * MEDIAN_HOP_CLTV_EXPIRY_DELTA + min_final_cltv_expiry
which in case of 3 hops equal to 24 hours / 1 day
. If the route/path found has a total cltv of exactly 24 hours
(path_total_cltv_expiry_delta), no shadow route will be added. If path_total_cltv_expiry_delta
is less than 24 hours
then a cltv less than or equal to the remainder from 24 hours will be added. In this case maker locktime can be 1.5 days if 1.5x is used. In general we can specify any constant maker locktime we want and the taker will have to find a route that matches the constraints, but for 3 hops as stated 1.5 days can be a good compromise, if the locktime is increased more routes can be found.
examples demonstrate the node having cltv_expiry_delta=10.
This is for demonstration purposes only.
Why rust-lightning uses 42 as default value and why it can't be decreased? Lowering it to minimum recommended 34 value could give us a noticeable outcome.
Most nodes use cltv_expiry_delta = 40
in their configs. It can be verified by checking the channels of the most connected nodes here, 40
and 144
are the most used numbers. I believe 40 is chosen because it's the default number in LND sample config, it gives a bit more safety than the recommended minimum of 34. I am not sure why 42 was chosen by rust-lightning, they maybe rounded the number of hours to 7 hours, or added 2 blocks to give the node better safety against chain reorganizations / transaction to appear on-chain. Also 42 is the answer to life the universe and everything 😁
First, Just adding a note about this to not forget :) The maker has to make sure that the final_cltv_expiry (last hop cltv) is less than the taker swap locktime (Assumed 22 hours for now). I will add this info to the above https://github.com/KomodoPlatform/atomicDEX-API/issues/1045#issuecomment-1310604403 to have a complete picture in one comment.
final_cltv_expiry (last hop cltv) should be more than taker swap locktime (at least double like other swaps to give the taker enough time to claim the lightning payment), not less. I miscalculated this, will update this in both comments now. Taker swap locktime (for other non-lightning coins) when Maker is lightning can be just the current implemented swap locktimes in mm2, not 22 hours.
This is a diagram to demonstrate swap locktimes if taker is LightningCoin
as explained in https://github.com/KomodoPlatform/atomicDEX-API/issues/1045#issuecomment-1310604403 https://github.com/KomodoPlatform/atomicDEX-API/issues/1045#issuecomment-1311755066
This is another diagram to demonstrate swap locktimes if maker is
LightningCoin
as explained in https://github.com/KomodoPlatform/atomicDEX-API/issues/1045#issuecomment-1310604403 https://github.com/KomodoPlatform/atomicDEX-API/issues/1045#issuecomment-1312062816
@artemii235 In this comment, I would like to propose a solution to how lightning taker fees can be implemented in AtomicDEX so that we can discuss this solution before proceeding with implementing this part of the lightning network integration.
invreq_payer_note
to the swap's secret hash.invreq_payer_note
set by the taker which is equal to the swap's secret hash.TakerFee
msg.invreq_payer_note
field is equal to the swap's secret hash.@smk762 after this PR https://github.com/KomodoPlatform/atomicDEX-API/pull/1592, new events that should be documented were added to MAKER_SUCCESS_EVENTS
, MAKER_ERROR_EVENTS
, TAKER_SUCCESS_EVENTS
, TAKER_ERROR_EVENTS
. These events are:
MakerPaymentInstructionsReceived
added to MAKER_SUCCESS_EVENTS
: This event is triggered alongside TakerFeeValidated
event (it's before it in order, if both are successful, both are triggered. If one of them fails TakerFeeValidateFailed
is triggered instead). It indicates that maker received inside the TakerFee
swap message instructions on how to send their payment and validated these instructions successfully. For protocols other than lightning the event success depends on taker fee validation success since no payment instructions are sent.TakerPaymentInstructionsReceived
added to TAKER_SUCCESS_EVENTS
: This event is triggered alongside MakerPaymentReceived
, MakerPaymentWaitConfirmStarted
events (it's before them in order, if all are successful, all are triggered. If one of them fails MakerPaymentValidateFailed
is triggered instead). It indicates that taker received inside the MakerPayment
swap message instructions on how to send their payment and validated these instructions successfully. For protocols other than lightning the event success depends on maker payment validation success since no payment instructions are sent.MakerPaymentRefundStarted
added to MAKER_ERROR_EVENTS
: This event is triggered after MakerPaymentWaitRefundStarted
event. It indicates that the refund process for maker payment has started successfully and any process required before it was successful.TakerPaymentRefundStarted
added to TAKER_ERROR_EVENTS
: This event is triggered after TakerPaymentWaitRefundStarted
event. It indicates that the refund process for taker payment has started successfully and any process required before it was successful.MakerPaymentRefundFinished
added to MAKER_ERROR_EVENTS
: This event is triggered after MakerPaymentRefunded
event. It indicates that any process needed after maker payment was refunded was successful.TakerPaymentRefundFinished
added to TAKER_ERROR_EVENTS
: This event is triggered after TakerPaymentRefunded
event. It indicates that any process needed after taker payment was refunded was successful."success_events": [
"Started",
"Negotiated",
"MakerPaymentInstructionsReceived",
"TakerFeeValidated",
"MakerPaymentSent",
"TakerPaymentReceived",
"TakerPaymentWaitConfirmStarted",
"TakerPaymentValidatedAndConfirmed",
"TakerPaymentSpent",
"TakerPaymentSpendConfirmStarted",
"TakerPaymentSpendConfirmed",
"Finished",
]
"success_events": [
"Started",
"Negotiated",
"TakerFeeSent",
"TakerPaymentInstructionsReceived",
"MakerPaymentReceived",
"MakerPaymentWaitConfirmStarted",
"MakerPaymentValidatedAndConfirmed",
"TakerPaymentSent",
"TakerPaymentSpent",
"MakerPaymentSpent",
"Finished",
]
"error_events": [
"StartFailed",
"NegotiateFailed",
"TakerFeeValidateFailed",
"MakerPaymentTransactionFailed",
"MakerPaymentDataSendFailed",
"MakerPaymentWaitConfirmFailed",
"TakerPaymentValidateFailed",
"TakerPaymentWaitConfirmFailed",
"TakerPaymentSpendFailed",
"TakerPaymentSpendConfirmFailed",
"MakerPaymentWaitRefundStarted",
"MakerPaymentRefundStarted",
"MakerPaymentRefunded",
"MakerPaymentRefundFailed",
"MakerPaymentRefundFinished",
]
"error_events": [
"StartFailed",
"NegotiateFailed",
"TakerFeeSendFailed",
"MakerPaymentValidateFailed",
"MakerPaymentWaitConfirmFailed",
"TakerPaymentTransactionFailed",
"TakerPaymentWaitConfirmFailed",
"TakerPaymentDataSendFailed",
"TakerPaymentWaitForSpendFailed",
"MakerPaymentSpendFailed",
"TakerPaymentWaitRefundStarted",
"TakerPaymentRefundStarted",
"TakerPaymentRefunded",
"TakerPaymentRefundFailed",
"TakerPaymentRefundFinished",
]
test_deserialize_lightning_swap_status
similar to the iris one here https://github.com/KomodoPlatform/atomicDEX-API/pull/1608@shamardy Please post the documentation links, notable libraries, and intermediate milestones reports to this issue comments.