Skip to content

Conversation

U65535F
Copy link

@U65535F U65535F commented Mar 9, 2025

A rewritten version of #9756 that is almost similar to it.
The previous source got deleted somehow (apologies).

de.is_subaddress = info.is_subaddress;
de.is_integrated = info.has_payment_id;

if (info.has_payment_id || !payment_id_uri.empty())
Copy link
Contributor

Choose a reason for hiding this comment

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

I know this isn't part of your change, but I'm curious why these two can contradict. In other words, is there a case where has_payment_id is false and payment_id_uri is not empty?

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think my comment here should hold up the PR, since it's not a change you made here, but I'd like to hear from someone else about this too.

@U65535F
Copy link
Author

U65535F commented Mar 20, 2025

@Tzadiko

@Tzadiko
Copy link
Contributor

Tzadiko commented Mar 20, 2025

@Tzadiko

One tag is fine to prod me in case I missed the emails sent by Github. No need to tag me on each of my comments 👍

@Tzadiko
Copy link
Contributor

Tzadiko commented Mar 20, 2025

You resolved a bunch of comments without them being addressed. I suggest we either come to a conclusion before they're resolved, or you make a change and push a commit. For example, after discussing I agree no further change is needed here, so it can be resolved.

@U65535F
Copy link
Author

U65535F commented Mar 20, 2025

You resolved a bunch of comments without them being addressed. I suggest we either come to a conclusion before they're resolved, or you make a change and push a commit. For example, after discussing I agree no further change is needed here, so it can be resolved.

Don't worry. Instead of letting you know every time (that seems spammy), I combined all of the suggestions into one commit and pushed them. Only time I will comment is when there is an issue.

@U65535F
Copy link
Author

U65535F commented Mar 21, 2025

I wonder why my test fixture isn't getting executed properly.

Traceback (most recent call last):
  File "/__w/monero/monero/tests/functional_tests/uri.py", line 369, in <module>
    URITest().run_test()
  File "/__w/monero/monero/tests/functional_tests/uri.py", line 48, in run_test
    self.test_multi_uri_two_payments()
  File "/__w/monero/monero/tests/functional_tests/uri.py", line 258, in test_multi_uri_two_payments
    wallet = multi_uri_common_variables["wallet"]
TypeError: 'URITest' object is not subscriptable
[TEST FAILED] uri

@Tzadiko
Copy link
Contributor

Tzadiko commented Mar 21, 2025

I wonder why my test fixture isn't getting executed properly.

Traceback (most recent call last):
  File "/__w/monero/monero/tests/functional_tests/uri.py", line 369, in <module>
    URITest().run_test()
  File "/__w/monero/monero/tests/functional_tests/uri.py", line 48, in run_test
    self.test_multi_uri_two_payments()
  File "/__w/monero/monero/tests/functional_tests/uri.py", line 258, in test_multi_uri_two_payments
    wallet = multi_uri_common_variables["wallet"]
TypeError: 'URITest' object is not subscriptable
[TEST FAILED] uri

Call the fixture to get the returned dictionary, then access it: multi_uri_common_variables()["wallet"]

@U65535F U65535F requested a review from Tzadiko March 21, 2025 13:24
@Tzadiko
Copy link
Contributor

Tzadiko commented Mar 21, 2025

Hey, Im going to stop reviewing this. There's been a persistent theme of you tagging me 8 hours after having not heard from me, and it's getting on my nerves. I've seen you do this with other people as well, people who have also spoken to you about this and asked you not to do it. I already spoke with you about this, and you said you're not going to continue pinging me. For example, not even 8 hours after leaving my last comment, you've pinged me again - I'm a human being, not a GPT, I need to sleep, I just woke up and I don't work for you (and even if I did, this would still be unacceptable). Not to mention, you're pinging me for issues that can be solved with simple debugging skills on code that you've supposedly written yourself - I'm unsure why you to ping me with regards to setting up a Python test fixture, there's plenty of documentation and examples online.

@Tzadiko
Copy link
Contributor

Tzadiko commented Mar 21, 2025

I spent a bunch of time reviewing this and trying to help you. I wasn't going to leave another comment, until I saw your recent force-push. Instead of doing your part by doing some basic debugging to address a roadblock you encountered that was prompted by my comment, you reverted your code to a point beforewhich my comment existed for expedience. It's apparent that you don't care for improving the quality of your submission (which would in turn increase its chances of being accepted), if it requires just a tiny bit of effort for you to figure out how to write a test fixture in Python.

I'm just as new as you, but this sort of lazy development doesn't have a place in this codebase, in my opinion. I do not recommend anyone else review this PR, you'll be wasting your time. OP will ignore it at the earliest sign of inconvenience if it means he gets his code crammed through faster.

@U65535F
Copy link
Author

U65535F commented Mar 21, 2025

I spent a bunch of time reviewing this and trying to help you. I wasn't going to leave another comment, until I saw your recent force-push. Instead of doing your part by doing some basic debugging to address a roadblock you encountered that was prompted by my comment, you reverted your code to a point beforewhich my comment existed for expedience. It's apparent that you don't care for improving the quality of your submission (which would in turn increase its chances of being accepted), if it requires just a tiny bit of effort for you to figure out how to write a test fixture in Python.

I'm just as new as you, but this sort of lazy development doesn't have a place in this codebase, in my opinion. I do not recommend anyone else review this PR, you'll be wasting your time. OP will ignore it at the earliest sign of inconvenience if it means he gets his code crammed through faster.

I realize now that my handling of this PR wasn’t ideal and clear enough. First off, a couple of clarifications:

  • When I force-pushed, I wasn’t discarding your review suggestions instead I squashed my commits into one to keep the history clean. The changes you pointed out are still included,
  • Mistakenly, I thought GitHub only notified people when they are directly tagged, so I didn’t realize my activity was pinging everyone too frequently. I'll be more mindful about that and be quieter.
  • Regarding the test fixture: it's apparent that you're right, I should have spent more time debugging on my own before asking. That would've saved reviewers some time.

I'm still fairly new to contributing to larger repositories, so I'm learning as I go (this time, the hard way). I really appreciate the effort you put into reviewing though it wasn’t at all wasted. I'll take this as a lesson to be more patient, clear about my next steps, and of course be considerate of reviewers time.

@nahuhh
Copy link
Contributor

nahuhh commented Mar 25, 2025

You'll need to drop the merge commit and use rebase instead

@U65535F U65535F force-pushed the master branch 2 times, most recently from dd12547 to de81583 Compare March 25, 2025 13:36
@U65535F
Copy link
Author

U65535F commented Mar 26, 2025

@selsta Please review the PR. The new version (v0.18.4.0) is almost released.

Major improvements from previous old review:

  1. Introduce new RPC commands: make_uri_v2 and parse_uri_v2: these will handle both single and multi recipient transactions. The old/legacy versions (i.e., make_uri and parse_uri) will be kept to fully ensure the backwards compatibility. (as suggested by iamamyth).
  2. Removed all noticeable unnecessary edits and also fixed minor nits (thanks to Tzadiko for pointing them out).
  3. Tests are passing successfully. Old tests have not been modified in any way.
    EDIT: The failing test is unrelated to the PR!

@U65535F
Copy link
Author

U65535F commented Mar 29, 2025

@selsta Hello, can you please tell me when you'll review this. I will patiently wait till that date.

@selsta
Copy link
Collaborator

selsta commented Mar 29, 2025

The three points you have written above all sound good and were necessary to get this merged.

In file src/wallet/wallet_rpc_server_commands_defs.h, please update WALLET_RPC_VERSION_MINOR to indicate API changes.

@selsta
Copy link
Collaborator

selsta commented May 9, 2025

I tested it in monero-wallet-cli and it looks good to me. I don't have any remaining suggestions at the moment.

@U65535F U65535F changed the title Adding multiple-URI support in parse_uri and make_uri wallet: add multiple-URI support to parse_uri and make_uri May 24, 2025
Copy link
Collaborator

@selsta selsta left a comment

Choose a reason for hiding this comment

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

I'm not sure if someone else is going to review this but from my side I'll add an approval.

@sa8ab
Copy link

sa8ab commented Jun 12, 2025

Is it possible to have multiple integrated addresses on one transaction?
Is it maximum 1 integrated address and rest sub address or primary addresses?

@U65535F
Copy link
Author

U65535F commented Jun 13, 2025

Is it possible to have multiple integrated addresses on one transaction?
Is it maximum 1 integrated address and rest sub address or primary addresses?

No multiple integrated addresses iirc.

Copy link
Collaborator

@selsta selsta left a comment

Choose a reason for hiding this comment

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

From what I can tell this is currently broken, doing

transfer 4JtkiNvoi3iSPHHvcfXPPyj66zHQ9h1X9hmLCjDZ6kbNUhtYwDhAMm79p9GZ1iPCUhDMEvKMkMJdgb7JURAkCZUuhxNZCGqxVNDAmjcimV 0.001
[wallet 49C5ha]: show_transfer 35c55d6cc0733dc211ff15668978a3237e6e6f5b1bd48ac0a72d658b48961aee
Outgoing transaction found
txid: <35c55d6cc0733dc211ff15668978a3237e6e6f5b1bd48ac0a72d658b48961aee>
Height: 3489288
Timestamp: 2025-08-30 18:02:15Z
Amount: 0.001000000
Payment ID: 0000000000000000
Change: 0.000006040000
Fee: 0.000030580000
Destinations: 4JtkiNvoi3iSPHHvcfXPPyj66zHQ9h1X9hmLCjDZ6kbNUhtYwDhAMm79p9GZ1iPCUhDMEvKMkMJdgb7JURAkCZUuhxNZCGqxVNDAmjcimV: 0.000001000000
Note: 

does not add the payment ID correctly

Copy link
Contributor

@jeffro256 jeffro256 left a comment

Choose a reason for hiding this comment

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

I have some disagreements about the code structure, and the URI format itself.

Comment on lines 1644 to 1652
std::string custom_convert_to_url_format(const std::string &uri) const;
std::string make_uri(const std::vector<std::string> &addresses, const std::vector<uint64_t> &amounts, const std::vector<std::string> &recipient_names, const std::string &tx_description, std::string &error) const;
Copy link
Contributor

Choose a reason for hiding this comment

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

These new methods, including parse_uri(), do not need to be member functions of wallet2. I would recommend making them free functions. If they aren't to be free functions, at the very least mark the member functions as static, please.

{
if (!m_wallet) return not_open(er);
std::string error;
std::string uri = m_wallet->make_uri(req.addresses, req.amounts, req.recipient_names, req.tx_description, error);
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 why we shouldn't have make_uri()/parse_uri() be member functions of wallet2: you need to have initialized a wallet2 instance for no reason.

std::vector<std::string> addresses;
std::vector<uint64_t> amounts;
std::vector<std::string> recipient_names;
if (!m_wallet->parse_uri(req.uri, addresses, amounts, recipient_names, res.uri.tx_description, res.unknown_parameters, error))
Copy link
Contributor

Choose a reason for hiding this comment

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

Same point here

}

if (amount > 0)
std::string uri = "monero:" + addresses_str;
Copy link
Contributor

@jeffro256 jeffro256 Aug 30, 2025

Choose a reason for hiding this comment

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

I don't like the format of <all addresses>?<all amounts>&<all messages>, etc. Take a look at Bitcoin Unlimited's (node for Bcash) multiple address URI scheme: https://github.com/BitcoinUnlimited/BUIP/blob/master/086.md. The address, amount, and labels are next to each other for each output, which makes for more readable URIs. More importantly however, this allows the field for each output to remain undefined if desired. See this example for an actual use case: https://github.com/BitcoinUnlimited/BUIP/blob/master/086.md#example-1-bar-transaction. Here you can see that the amount field for a tip output at a bar is left empty, which triggers the client code to prompt the user to enter a desired amount. Overall, this type of URI format is way more flexible and future-proof than cramming values into a list based on field type, assuming the same structure for every single output in a transaction.

Copy link
Collaborator

@selsta selsta Aug 30, 2025

Choose a reason for hiding this comment

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

FWIW this is the format we decided on. I don't remember why exactly.

https://github.com/monero-project/monero/blob/master/docs/URI_SCHEME.md

Copy link
Contributor

Choose a reason for hiding this comment

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

Is it too late to change it if no one has a working implementation yet AFAIK?

Copy link
Collaborator

Choose a reason for hiding this comment

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

#7731 (comment)

Here is some background on when it was decided on. I'm not sure if anyone actually implemented this.

Copy link
Contributor

Choose a reason for hiding this comment

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

Seems like @trasherdk and @benevanoff wanted a similar approach to what I am bringing up here: packing info per-output, instead of packing per-value-type.

Choose a reason for hiding this comment

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

Seems like @trasherdk and @benevanoff wanted a similar approach to what I am bringing up here: packing info per-output, instead of packing per-value-type.

As far as I know, XMRChat is the first and only one to use this, and we don't have anything in prod yet. We're fine with whatever format you prefer. Just hope it can be done quickly as we'd like to implement this soon.

Copy link

@iamamyth iamamyth Sep 10, 2025

Choose a reason for hiding this comment

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

I think the design goal here was for the multi-payment scheme to match the original single-payment scheme in case of a single payment, i.e. it merely extends the existing scheme, rather than replacing it, making for a graceful upgrade (in particular, newly generated single-payment URIs work fine with existing consumers). That said, one could argue a "graceful" upgrade creates a false continuity, as multi-payments might parse OK with software that only supports single payments, making for user headaches. In any case, looking at the current tests, something has gone way off the rails, because the tests now include an output parameter, which they shouldn't.

If you want to change the scheme, such that it's not compatible with the old one, it should be a clean break (i.e. a new scheme name), otherwise you end up violating the core principle of URI namespacing.

Copy link
Author

Choose a reason for hiding this comment

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

I get what you're saying. The solution is to change the scheme name so the old clients don't accidentally parse the new multi recipient URI. I wonder what should be the new URI scheme name if that's what you mean? Additionally, should the new functions parse and generate old scheme URIs if there's it's a single recipient?

Choose a reason for hiding this comment

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

We can't decide on minor issues like the scheme name before resolving the major question of whether to split the scheme at all. So, it seems any work should be on hold for now. I see two decent options:

  1. Extend the scheme to preserve the single-payment format and intentionally differ from it for multi-payment URIs in a manner that makes it highly unlikely multi-payment URIs introduce false compatibility.
  2. Keep the current single-payment URI scheme as-is, and introduce a new, multi-payment URI scheme.

In either case, I think single-payment URIs should work as-is (i.e. no changes to the single-payment use case, anything that previously worked will still work); otherwise, a lot of software breaks for a minor upgrade.

Copy link
Author

@U65535F U65535F Sep 11, 2025

Choose a reason for hiding this comment

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

Can we not modify the old functions to reject the URI as multi-recipient if it contains any output parameter? If this is possible, this would eliminate the problem of false compatibility if I'm not wrong?

@U65535F U65535F force-pushed the master branch 7 times, most recently from 9d2f644 to 2b2ffe7 Compare September 5, 2025 18:39
@U65535F U65535F force-pushed the master branch 8 times, most recently from 41c9746 to 4b10655 Compare September 7, 2025 15:39
@U65535F
Copy link
Author

U65535F commented Sep 8, 2025

@selsta Can you review the new code. I think I have fixed the problem in the wallet cli. You can test it and see if it works now (I've tested from my side). One thing I want to point out is that it only adds payment id when you explicitly provide a payment_id parameter in the uri. Otherwise it wouldn't add, you've seen this and requested the changes. Additionally, @jeffro256 can you please review the new code (in the uri.cpp)? Is that the format that you expected?
Is the uri.cpp and uri.hpp at the right place? Should I introduce wrappers around the new functions in the wallet code? What do you think?

@selsta
Copy link
Collaborator

selsta commented Sep 10, 2025

I will re-review but need a bit of time

@FiatDemise
Copy link

Am I understanding correctly that this is the new format? Is there supposed to be a question mark at the beginning?

monero:?output=address1;amount1;&output=address2;amount2;

@iamamyth
Copy link

Am I understanding correctly that this is the new format? Is there supposed to be a question mark at the beginning?

monero:?output=address1;amount1;&output=address2;amount2;

Per my comment, this looks wrong, as the original scheme specification (https://github.com/monero-project/monero/blob/master/docs/URI_SCHEME.md) contains no mention of an output param, and the single-output case should match the old format.

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

Successfully merging this pull request may close these issues.

9 participants