Skip to content

Support passing preimage for spontaneous payments #549

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

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

aagbotemi
Copy link

This PR adds support for specifying custom preimages when sending spontaneous (keysend) payments.

Solution

  • Added send_with_preimage() method
  • Added send_with_preimage_and_custom_tlvs() method for advanced use cases
  • Modified internal send_inner() to accept optional preimage parameter and generate random preimage only when custom preimage is not provided.

An integration test is added to verify logic, and the new methods are added to the bindings.

Fixes #535

@ldk-reviews-bot
Copy link

ldk-reviews-bot commented May 31, 2025

👋 I see @TheBlueMatt was un-assigned.
If you'd like another reviewer assignemnt, please click here.

Copy link

@chuksys chuksys left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just shared a few thoughts regarding the overall design of this API and its extensibility.

/// Send a spontaneous with custom preimage
pub fn send_with_preimage(
&self, amount_msat: u64, node_id: PublicKey, sending_parameters: Option<SendingParameters>,
preimage: PaymentPreimage,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if we should expand the purpose of SendingParameters a bit to allow passing of any custom parameters required for sending payments (not just routing and pathfinding parameters).

This approach would allow us to include preimage as an Option within SendingParameters, providing a single, coherent place for all payment-sending customizations.

A significant benefit of this change would be the ability to deprecate or drop specialized functions like send_with_preimage and send_with_custom_tlvs (in another PR), reducing overall boilerplate for users.

What do you think about this?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I initially hesitated about mixing routing parameters with payment content. Your point about expanding SendingParameters to handle all payment customization makes sense for the long-term API design, and the benefit outweigh the conceptual mixing.

I'll refactor to move preimage into SendingParameters as an Option. I can drop the send_with_preimage and send_with_preimage_and_custom_tlvs, then send_with_custom_tlvs can be dropped in another PR.

Thank you.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if we should expand the purpose of SendingParameters a bit to allow passing of any custom parameters required for sending payments (not just routing and pathfinding parameters).

Ah, no, I don't think we should do that. Note that after LDK 0.2 release (cf. #462) we'll replace SendingParameters with LDK's RouteParametersConfig everywhere, so really shouldn't make any changes prior to it. Also, while we might be fine to expose the preimage for keysend payments, I don't think we'd like to allow users to override it for BOLT11/BOLT12 generally.

I'll refactor to move preimage into SendingParameters as an Option.

Please revert this. I think we can either have separate send APIs as you previously suggested, or add the preimage as an optional field to the existing ones. Will take a look after the revert, but your previous approach might be fine.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, no, I don't think we should do that. Note that after LDK 0.2 release (cf. #462) we'll replace SendingParameters with LDK's RouteParametersConfig everywhere, so really shouldn't make any changes prior to it. Also, while we might be fine to expose the preimage for keysend payments, I don't think we'd like to allow users to override it for BOLT11/BOLT12 generally.

Thanks for the clarification!

self.send_inner(amount_msat, node_id, sending_parameters, Some(custom_tlvs), None)
}

/// Send a spontaneous with custom preimage
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you missed the word "payment" here (after spontaneous) - that's if we'd still be adding this method.

Copy link
Author

@aagbotemi aagbotemi Jun 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I missed that. Thank you. I am removing the method.

Copy link

@chuksys chuksys left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are going to use sending_parameters to pass in the custom preimage, I think we should allow the user to set it in config or pass it directly.

@@ -77,7 +77,10 @@ impl SpontaneousPayment {
return Err(Error::NotRunning);
}

let payment_preimage = PaymentPreimage(self.keys_manager.get_secure_random_bytes());
let payment_preimage = sending_parameters
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are doing this, I think we'll need to use override_params instead as that allows send_inner to select sending_parameters set in the config (if not passed into the send method directly).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I don't think we should do this, see above.

@tnull tnull removed the request for review from TheBlueMatt June 2, 2025 11:15
Copy link
Collaborator

@tnull tnull left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned above I don't think adding this field to SendingParameters is the way to go here (note it would also allowing setting global default preimage if users would override the field in Config, which is actually dangerous as preimages can never be reused). Please revert to you previous draft, will review then.

@@ -77,7 +77,10 @@ impl SpontaneousPayment {
return Err(Error::NotRunning);
}

let payment_preimage = PaymentPreimage(self.keys_manager.get_secure_random_bytes());
let payment_preimage = sending_parameters
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I don't think we should do this, see above.

@aagbotemi
Copy link
Author

Please revert to you previous draft, will review then.

Alright. Will do that. Thank you.

@aagbotemi
Copy link
Author

Please revert to you previous draft, will review then.

Hello @tnull, I have reverted to the previous draft. This is ready.

@Camillarhi
Copy link
Contributor

Camillarhi commented Jun 2, 2025

Nice work on this PR! The custom preimage functionality is implemented cleanly, and the test coverage looks good.

One small enhancement suggestion: we could add verification that node_b received the payment to complete end-to-end verification of the payment flow.

@aagbotemi
Copy link
Author

One small enhancement suggestion: we could add verification that node_b received the payment to complete end-to-end verification of the payment flow.

Thanks for the suggestion! I've added the end-to-end verification as requested. It also ensure the custom preimage flows correctly through the entire payment process from sender to receiver.

Copy link
Collaborator

@tnull tnull left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically LGTM, but now that we actually take a PaymentPreimage from user input we should probably avoid the UniffiCustomTypeConverter for it, and rather expose a 'proper' newtype wrapper for the bindings. See #542 for inspiration on this, for example.

@@ -213,6 +213,10 @@ interface SpontaneousPayment {
PaymentId send_with_custom_tlvs(u64 amount_msat, PublicKey node_id, SendingParameters? sending_parameters, sequence<CustomTlvRecord> custom_tlvs);
[Throws=NodeError]
void send_probes(u64 amount_msat, PublicKey node_id);
[Throws=NodeError]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Let's move these new entries to the correct location w.r.t. API, i.e. below send_with_custom_tlvs.

/// Send a spontaneous payment with custom preimage
pub fn send_with_preimage(
&self, amount_msat: u64, node_id: PublicKey, sending_parameters: Option<SendingParameters>,
preimage: PaymentPreimage,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we add this as a new required parameter, let's move it before the optional parameters, i.e., Option<SendingParameters> (here and below).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, will fix it. Thank you.

@aagbotemi
Copy link
Author

Basically LGTM, but now that we actually take a PaymentPreimage from user input we should probably avoid the UniffiCustomTypeConverter for it, and rather expose a 'proper' newtype wrapper for the bindings. See #542 for inspiration on this, for example.

Thank you for the feedback, I will fix it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support passing preimage for spontaneous payments
5 participants