Skip to content
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

add NWC commands #1152

Closed
wants to merge 2 commits into from
Closed

add NWC commands #1152

wants to merge 2 commits into from

Conversation

elnosh
Copy link
Contributor

@elnosh elnosh commented Apr 21, 2024

for #1120 added multi_pay_invoice, pay_keysend, multi_pay_keysend and list_transactions NWC commands. I added those requests to the mutinynet faucet to help me test these from the UI.

Reasoning for certain changes I did:

  • I changed the return type and place where we were broadcasting the response events from the NWC requests. Discussed with @benthecarman and did this because some of the new commands (multi_pay_invoice and multi_pay_keysend) can return multiple events. So instead of waiting to return them until start_nostr method, now broadcasting in the respective handle methods where the response events are generated.
  • changed the type for add_payment and remove_payment because they were previously taking a Bolt11Invoice so I changed it to TrackedPayment to now be able to accommodate adding keysend payments as well instead of only invoices.
  • added an optional preimage param to the keysend payment method. This is to generate the preimage deterministically from the request event for the nwc keysend payment to avoid paying the same keysend twice if we try to process the same event.
  • added some methods to the InvoiceHandler trait that I needed for the new commands.

@benthecarman benthecarman linked an issue Apr 22, 2024 that may be closed by this pull request
4 tasks
Copy link
Collaborator

@benthecarman benthecarman left a comment

Choose a reason for hiding this comment

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

overall looking good

Comment on lines 566 to 578
nostr_manager: &NostrManager<S, P, C>,
) -> anyhow::Result<Option<NwcResponse>> {
Copy link
Collaborator

Choose a reason for hiding this comment

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

for all of these you're passing in the NostrManager which forces you to put all the type params and stuff but you only end up calling client.send_event, would be better to just pass in the nostr client

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ahh yeah, thanks

Comment on lines 685 to 688
let incoming = match params.transaction_type.unwrap() {
TransactionType::Incoming => true,
TransactionType::Outgoing => false,
};
Copy link
Collaborator

Choose a reason for hiding this comment

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

this can be simplified to let incoming = params.transaction_type.unwrap() == TransactionType::Incoming

};
let preimage = PaymentPreimage(Sha256::hash(input.as_bytes()).into_32());
Copy link
Collaborator

Choose a reason for hiding this comment

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

We need to incorporate some sort of secret here so its not derivable from public data, should also hash in the server private key for this nwc.

mutiny-core/src/nostr/nwc.rs Show resolved Hide resolved
Comment on lines 1270 to 1271
code: ErrorCode::PaymentFailed,
message: String::from("not enough balance to make payment"),
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think it'd be better to do an UNAUTHORIZED here with a better error string about the budget

Copy link
Contributor Author

Choose a reason for hiding this comment

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

what error message do you think would be good here?

Copy link
Collaborator

Choose a reason for hiding this comment

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

"Keysend only supported for profiles with a budget"

.unwrap_or(self.profile.name.clone());
// attempt keysend payment now
match node
.keysend(to_node_pubkey, sats, None, vec![label], Some(preimage.0))
Copy link
Collaborator

Choose a reason for hiding this comment

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

you're never doing anything with the TLV records will need to add that to the keysend function too

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@TonyGiorgio passing that optional preimage here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@benthecarman did some changes to include the TLV records. I changed the previous message param and passing new Vec<CustomTLV>. This would require changes in the frontend tho. I saw the frontend was not passing a message anyways so it would be changing from undefined to an empty array. Let me know what you think

@@ -1617,6 +1617,7 @@ impl<S: MutinyStorage> Node<S> {
message: Option<String>,
labels: Vec<String>,
payment_id: PaymentId,
preimage: Option<[u8; 32]>,
Copy link
Contributor

Choose a reason for hiding this comment

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

This is added but it's never used. I don't know why it would be useful.

Copy link
Collaborator

Choose a reason for hiding this comment

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

this is used from the NWC stuff, allows for specifying a preimage for the keysend.

We need it for ourself as well so we don't generate a completely random preimage for the event, need to do it deterministically so if we process the event multiple times we won't send the payment multiple times

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm generating the preimage deterministically from the nwc request event in the handle_nwc_keysend_payment method and passing it as an option. Got from @benthecarman that this would be needed to avoid making another keysend payment for the same event in case we try to process that same request event more than once.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

whoops, saw your comment after posted mine lol

Copy link
Contributor

Choose a reason for hiding this comment

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

I looked and didn't see it. Where is it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@elnosh
Copy link
Contributor Author

elnosh commented Apr 23, 2024

thanks for the feedback. Added some changes based on it

Copy link
Collaborator

@benthecarman benthecarman left a comment

Choose a reason for hiding this comment

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

few nits, and hoping you can improve the tests a bit

.into_iter()
.map(|tlv| (tlv.tlv_type, tlv.value.encode()))
.collect();

RecipientOnionFields::secret_only(payment_secret)
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think we need to change this to spontaneous_empty as well, probably will get the same error as before

RecipientOnionFields::secret_only(payment_secret)
.with_custom_tlvs(vec![(34349334, msg.encode())])
.with_custom_tlvs(custom_tlvs)
.map_err(|_| {
log_error!(self.logger, "could not encode keysend message");
MutinyError::InvoiceCreationFailed
Copy link
Collaborator

Choose a reason for hiding this comment

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

can you make this InvalidArgumentsError, that'd be more fitting here

SpendingConditions::Budget(mut budget) => {
// generate deterministic preimage for keysend payment from event info
let preimage = match params.preimage {
Some(preimage) => PaymentPreimage(Sha256::hash(preimage.as_bytes()).into_32()),
Copy link
Collaborator

Choose a reason for hiding this comment

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

shouldn't hash the preimage here, we should be using what they gave us

Comment on lines 689 to 722
if params.limit.is_some() {
let limit = params.limit.unwrap() as usize;
if limit - 1 < transactions.len() {
transactions = transactions[..limit].to_vec();
}
}
if params.offset.is_some() {
let offset = params.offset.unwrap() as usize;
if offset - 1 < transactions.len() {
transactions = transactions[offset..].to_vec();
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

we have similar logic here: https://github.com/MutinyWallet/mutiny-node/blob/master/mutiny-core/src/lib.rs#L1805

i would just copy this logic, should probably have tests around this as well

node.expect_keysend()
.once()
.returning(move |_, _, _, _, preimage| {
let payment_preimage = PaymentPreimage(preimage.unwrap());
Copy link
Collaborator

Choose a reason for hiding this comment

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

should assert the preimage, pubkey, and amount are what we expect

@elnosh elnosh force-pushed the nwc-commands branch 2 times, most recently from a382b4b to f855a0a Compare April 24, 2024 04:40
@TonyGiorgio
Copy link
Contributor

I don't think we should support any of these commands. Sorry for the wasted effort but a strong NACK from me.

@elnosh
Copy link
Contributor Author

elnosh commented Apr 24, 2024

I don't think we should support any of these commands. Sorry for the wasted effort but a strong NACK from me.

no worries! got to learn about NWC and how that part of Mutiny works, so not a waste at all

@elnosh elnosh closed this Apr 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add missing NWC commands
3 participants