- 
                Notifications
    You must be signed in to change notification settings 
- Fork 421
feat: Implement self payment #3934
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
| 👋 I see @joostjager was un-assigned. | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be preferable if we'd avoid adding a special API for self-payments at this point. Can't we just detect that it's a self payment in send_payment and act accordingly?
        
          
                lightning/src/ln/channelmanager.rs
              
                Outdated
          
        
      | /// | ||
| /// # Returns | ||
| /// Returns the payment hash on success, or an APIError on failure. | ||
| pub fn send_self_payment( | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, not sure we want to add a special API just for this 1-hop circular route. Can we reuse the existing APIs, i.e. detect that we're the recipient and act accordingly? Then, for #3791, we'll need to add an API that allows longer circular routes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I originally thought of using send_payment_with_route since we know the route we want the payment to take . I should be able to incorporate it in that .
        
          
                lightning/src/util/scid_utils.rs
              
                Outdated
          
        
      | // Self payment scid is 0 to avoid confusion with real channels | ||
| /// A special short channel ID (0) used to indicate a self-payment. | ||
| /// When routing a payment to ourselves, the first hop will have this SCID. | ||
| pub const SCID_SELF_PAYMENT: u64 = 0; | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, when handling HTLCs we're already leaning on the short_channel_id == 0 special case for receiving. So I guess that's preexisting. Still, I'm not the biggest fan of such magic numbers. Do you think there would be a way to avoid this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A way I thought of is to change Route or RouteParameters to include a is_self_payment flag which can be used to detect if a payment is a self-payment or we could use if path.hops.first().unwrap().pubkey == our_node_pubkey but I don't feel good about the idea of having to pass our_node_pubkey deep in the api calls to send_payment_along_path. either way we would want to have a magic number for dummy scid (not specific for self-payments but general ) and settle on it ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or we could use
if path.hops.first().unwrap().pubkey == our_node_pubkeybut I don't feel good about the idea of having to passour_node_pubkeydeep in the api calls tosend_payment_along_path
Hmm, but in ChannelManager (hence also in send_payment_along_path) we should have our pubkey readily available at self.our_network_pubkey, no?
| 👋 The first review has been submitted! Do you think this PR is ready for a second reviewer? If so, click here to assign a second reviewer. | 
955c11c    to
    7d78e4e      
    Compare
  
    | Codecov ReportAttention: Patch coverage is  
 
 Additional details and impacted files@@            Coverage Diff             @@
##             main    #3934      +/-   ##
==========================================
+ Coverage   88.84%   90.80%   +1.96%     
==========================================
  Files         166      167       +1     
  Lines      119487   143472   +23985     
  Branches   119487   143472   +23985     
==========================================
+ Hits       106157   130285   +24128     
+ Misses      11006    10722     -284     
- Partials     2324     2465     +141     
 Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
 | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please undraft/request review when you think this is ready for another look or have any more particular questions!
Normal lightning workflow does not know how to handle self payment as the route created is to self . This will not be found in short_to_chan_info as there cant be channel created where both the nodes are the same. This handles that scenario by handling the payment before the lookup is hit
        
          
                lightning/src/routing/router.rs
              
                Outdated
          
        
      | hops: vec![RouteHop { | ||
| pubkey: our_node_pubkey.clone(), | ||
| short_channel_id: 0 , // Dummy short_channel_id specifying self payment | ||
| fee_msat: 0, // Zero fees | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The cltv_expiry_delta field is currently hardcoded to MIN_FINAL_CLTV_EXPIRY_DELTA, but it should instead use the value from route_params.final_cltv_expiry_delta to maintain consistency with the requested payment parameters. This ensures that self-payments respect the same CLTV constraints as regular payments.
Spotted by Diamond
Is this helpful? React 👍 or 👎 to let us know.
61ebe05    to
    39643a5      
    Compare
  
    | I don't think this is ready for 2nd reviewer, or is it? | 
| if keysend_preimage.is_some() { | ||
| pending_events.push_back((events::Event::PaymentSent { | ||
| payment_id: Some(payment_id), | ||
| payment_preimage: keysend_preimage.unwrap(), | ||
| payment_hash: *payment_hash, | ||
| amount_msat: Some(htlc_msat), | ||
| fee_paid_msat: Some(0), // No fees for self-payments | ||
| bolt12_invoice: None, | ||
| }, None)); | ||
| } | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The implementation currently generates PaymentSent events only for spontaneous payments (with keysend_preimage), but not for Bolt11 invoice payments. This creates inconsistent behavior where Bolt11 self-payments will appear as claimable but never as sent.
For consistency in the payment lifecycle, both types of self-payments should generate both events. Consider modifying the code to handle Bolt11 self-payments similarly to spontaneous payments by generating the appropriate PaymentSent event when the payment is claimed.
| if keysend_preimage.is_some() { | |
| pending_events.push_back((events::Event::PaymentSent { | |
| payment_id: Some(payment_id), | |
| payment_preimage: keysend_preimage.unwrap(), | |
| payment_hash: *payment_hash, | |
| amount_msat: Some(htlc_msat), | |
| fee_paid_msat: Some(0), // No fees for self-payments | |
| bolt12_invoice: None, | |
| }, None)); | |
| } | |
| // Generate PaymentSent event for both keysend and Bolt11 self-payments | |
| pending_events.push_back((events::Event::PaymentSent { | |
| payment_id: Some(payment_id), | |
| payment_preimage: keysend_preimage.unwrap_or_else(|| payment_preimage.unwrap()), | |
| payment_hash: *payment_hash, | |
| amount_msat: Some(htlc_msat), | |
| fee_paid_msat: Some(0), // No fees for self-payments | |
| bolt12_invoice: None, | |
| }, None)); | 
Spotted by Diamond
Is this helpful? React 👍 or 👎 to let us know.
| 
 I just opened it from draft to get feedback and bot immediately assigned . | 
fixes #2462
revives #2573
This PR implements the option for self payment for ldk nodes .
PR is right now marked as draft as this is a very rough implementation and I am looking for suggestions / improvements , some of them
1 . should an option to make BlindedPath for self-routes be made ?
2 . should MPP be allowed ? (Personally I think this is a bad idea , we should use BlindedPath instead if we want privacy otherwise normal way should suffice)
3. Should all self-payments be spontaneous ? an observer might be able to figure out that that we are paying to ourselves if there are a lot of spontaneous payments !
4. My bad code ?