-
Notifications
You must be signed in to change notification settings - Fork 48
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
XLS-5d Standard for Tagged Addresses #6
Comments
Although this is still a spec / proposal, I'd like to tag some people that are involved with promiment wallets, to ensure visibility and to give them a chance to participate in refining this spec. Edge Wallet: @paullinator Please add others, as necessary. |
@nbougalis Thank you! I'm happy to implement this in the projects + libs I'm working on + spread the word (explain it to devs/exchanges/users) once this is implemented. This will definitely help fight user error. |
Agreed with "This will definitely help fight user error." +1 to implement it too. |
So while I like the proposal. Seems it should also be compared to just having a standard URI format that also allows the destination tag to be included.
This has some advantages:
Was there a reason this approach wasn't considered? Perhaps I am missing something. |
Thanks for the comments @zquestz. I appreciate the question. We did consider this and no, you aren't really missing anything. I simply didn't lay out our rationale for not adopting the URI-style format. The problem with the URI format is that:
The URI syntax is (mostly) not subject to these issues primarily because the tools we use to display content where I'd expect to find such URIs embedded will, typically, detect URLs and make them clickable, reducing the possibility of end-user error. If there's support for this new format, then we should also augment the proposed URI spec to ensure that it includes support for packed addresses and define the expected behavior if a packed address is specified along with a |
I just published a node/javascript lib. to encode/decode based on the proposal by @nbougalis. The |
There needs to be some sort of incentive to switch over, otherwise we're all playing a game where the best course of action for all is to wait for the competitors to bear the cost of educating users and fielding support requests. Switching to Segwit addresses on BTC etc. has an incentive. Lower fees. Switching to this new format might decrease destTag mismatch errors, but it will increase confusion and other types of support tickets. I would much rather a standard for destination tag checksums be created. ie. increase the size of destTag to 64 bit, take the number you want to use, do some checksum math to get a number from 0-9999. Add that 4 digit checksum to the number multiplied by 10000 etc. That way:
tl;dr This address proposal will have a hard time with adoption unless someone goes around offering money to exchanges to support it. It would be much better to create a checksum feature to tag on to DestinationTag. |
@junderw I think there's incentive at exchanges etc. already, since it will save them a lot of support questions and manual corrections in the long term, users making mistakes with the tags, sending with tag zero, etc. Of course it would take a (relatively long) period where users can use both formats, but that's relatively easy to explain. I may even put up a small website with a address+tag converter & explanation so all platforms can link to that info. I agree @ the confusing part, but with a few lines and both options and a decent UI it should work. If we want to improve the destination tag user experience (so: not a separate tag but one checksummed packed address you can easily copy-paste at once) now is the time to do it, since there aren't that many users in the grand scheme of things. |
99% of people using exchanges are not the type to go on twitter to find a guy who made a converter, or even people that would even regularly check any of Ripple Labs' official channels to read about the change. Most users get 100% of their info from the exchanges they use, and the support teams of those same exchanges. Obviously having a conversion site would be a great resource our support team could link to, but it will still require a significant load on Customer Support.
These problems are just as easily fixed with an officially supported destination tag checksum. Even a 2 digit base-10 checksum will catch 99% of mis-entries. And if our account has the But with the currently proposed new-address system, this problem is only solved under the assumption that our competitors support withdrawals using the new address. AND assuming that we offer both encodings and the competitor does not dynamically detect the addresses during withdraw (ie. they make the user flip a switch) it could be possible that they get stuck trying to send to us, and they lose valuable trading time that could have been performed on our platform instead of our competitor's while they wait for support to answer their question. I agree that the destination tag being a separate entity was a bad idea to start with. But right now, we have to weigh the decision "will supporting this new format end up being a plus or minus for us?" and I am not fully convinced it will be a plus. So it won't be implemented it until exchanges see it as a plus. I personally am not convinced. |
The "two's complement" mention in this proposal doesn't make sense to me since tags are unsigned integers |
Good point. Unless there’s a reason we would want negative dest tags under the 64bit standard that just serves to confuse |
Hi @junderw . Could you clarify what you mean here by "officially supported"? |
ie. similar to asfRequireDest, a new flag called asfRequireDestChecksum could tell the network to reject deposits that have a dest tag with invalid checksum. with 32 bits being so low, a 2 digit (base 10) checksum is all we could spare... but it helps. However, if the network actually rejected transactions for us it would help. Not to mention if there was a standard we could add withdrawal validation. Thanks. |
@junderw, thanks for your comments. I like the idea of a destination tag checksum and it could address one of the problems this proposal aims to solve, but as you point out there is an issue with the number of available bits to spare for a checksum, which would have to be fixed for this to be, as you wrote, "officially supported" (i.e. well defined and part of the protocol, so that Even if implemented, the checksum addresses only one problem though. In my experience a separate address and destination tag pose a challenge for users, exchanges and wallets and the tagged addresses could help improve the UX for users. In a perfect world, using a well-defined URI (see issue #3) would be enough, but we don't live in a perfect world. I will grant you that the tagged address system isn't perfect. But, imo, it's better than the existing alternative. |
perhaps a feature request for a dtag checksum should be separate thing. As far as this address proposal is concerned, "needs a much larger incentive then currently exists", and "early adopter exchanges have a high cost for zero benefit (99% of deposit/withdraw are to other exchanges, so it won't get used at all until other exchanges use it) "If only this were implemented from the beginning" is the sentiment. |
An extreme example of a "chicken and egg" problem. Ripple Labs should get behind this and offer incentives / dev resources to integrate. That's the only way I see this getting adoption. |
In my opinion it's possible to get attention of some big exchangers. If they see such implementation is worth the hassle as it dramatically decrease all the xrp tickets with missed/incorrect destination tags, then they will do it. Some exchangers didn't want to support BCH or ETH, but anyway started to support it as they saw a profit in it. Changing old Ripple logo to a new XRP logo didn't bring much profit to exchangers, but they still managed it (probably because of xrp community power). To minimise confusion the update can be cooperated, and best UI practises for a transition period can be shared. Roll out schedule, and announcement across different platforms also can be synced. |
@ihomp I completely agree. I'm working on a simple website with option for community translations where with a simple explanation, some samples and an encoder/decoder, so clients and exchanges can link to that site if they want to allow people to read more about it. |
Added all proposal into one lib that encodes+decodes for node, & info in the Readme: https://github.com/xrp-community/xrpl-destination And it's really hard to pick one; Existing Packed Appended X-Address |
Doesn't seem to be much progress here? My "proposal" was mostly just some fun, but I regret even putting it out there, as it's just a spanner in the works. I got another email from some poor soul that lost money. Interesting to note that they didn't realize the destination tag changed per transaction at the particular gateway. This is still a real problem. |
That's odd. Does the gateway actually lose funds after the first transaction to a particular destination tag? If you haven't already, review the following proposal: https://github.com/intelliot/x-address-proposal Gateways can encode an optional expiration timestamp into the address, which would ensure that the address would become invalid after e.g. 24 hours. Of course, this requires support from the client wallet, but I'm optimistic that we can get that to happen, especially since we will provide implementations in JavaScript and C++. |
Yah, I have glanced over your proposal of course. I am slightly in favor of
it :) Due to the expiry.
Then again, if people are using random, per transaction tags, Nik’s simple,
essentially opaque, format works for me.
Shrug. Maybe could add expiry, and X prefix to Nik’ format.
I can’t recall the details of the email off hand but they used an old
destination tag apparently. I’ll forward it on to you after I have finished
at gym.
|
I'm in support of changing the prefix in xls5d to x or similar. It's too confusing to users otherwise |
@sublimator @codetsunami Agree. I'm opting for the proposal by @nbougalis (since it's a really clean solution) but changing the prefix to map to an I'll be coding a TS implementation this week 👍 |
Nice! People will be happy to not lose their money!
… |
@sublimator just to be clear no one will lose their money for lack of providing a dest tag. It is the exchange/counterparty not doing the right thing (i.e. returning un-tagged payments) which is the issue there. Obviously making an address format where the tag can't be accidentally excluded helps but the fault for lost funds remains with the exchange/counterparty. It's not as though the XRP is burnt by the network if the dest tag is excluded. |
Building hundreds of bells and whistles into the address format can't actually reduce irreducible complexity. It can improve UX, that's about it. If the exchange has transient endpoints the user needs to be aware of this no matter what. Imho making expirable address formats will cause at least as much confusion as it solves. Imagine sending someone an endpoint you know is correct only to have the payment rejected because the endpoint expired. Bad UX. |
Correct: improving UX is the goal here, and it is pretty important. What do you mean by "endpoint"? Having the payment rejected with 'invalid address' is a much better UX than losing funds. |
An endpoint is a location to pay to |
@intelliot
I have seen various types of issues.
I believe an expiry would help in some cases, yes.
|
Expiring addresses face another problem: if I look at an account’s history on an explorer like bithomp, I’ll be unable to see expiring addresses even for transactions where I used them, since the necessary information (expiration time) isn’t available, although workarounds could be developed (e.g. waste could store the expiring addresses as a memo). Knowing I sent to With this spec, both the classic and the tagged address can be displayed since all the infrormation displayed, which alleviates this issue I think. |
i don’t think weitze (sic??) ended up using expiry for various reasons. I
can’t recall exactly why, but his explanation made sense to me and probably
aligns with yours.
“Seemed like a good idea at the time” lol
|
I hadn't thought of this but yes chain explorers will struggle to display up to 2^32 'X' addresses for every 1 'r' address. No problem if they enter the 'X' address for the lookup, but if they enter an 'r' address and want to find all 'X' addresses, for an exchange account this will be impossible to display. |
The simple packed method shares no common prefix with the actual
destination address (so unless you do backflips) ... so X or r leading
prefix byte is irrelevant somewhat ... unless I am confused about what you
are saying ...
|
@sublimator yes I’m saying that looking up a packed address in an explorer is fine, but if you look up a regular address in an explorer there’s a good chance the explorer won’t be able to tell you all the packed addresses that have been used for that regular address. Consider an exchange account with a new dtag for each deposit. There would be hundreds of thousands or more packed addresses to display. May not be a real issue but in terms of user cognition of which addresses are associated with which ledger account there’s a break there. |
@codetsunami I guess the explorer will only show them when they apply, on a per tx basis. |
Sounds tricky
I don't really have anything useful to say as I don't have the bandwidth
this deserves and am not quite following you
You can do all sorts of crazy stuff to make the addresses share common
prefixes but it would be very hard to get it implemented across various
languages
You are imagining the addresses being first class/indexed concepts in
explorers?
… |
@WietseWind it’ll have to be something along those lines yeah. But I can see for new users how this will be even more confusing that dtags were to begin with. In a sense we’ve traded input complexity for cognitive complexity— now users need to understand two types of addresses and how they’re linked. Ultimately probably not a bad trade-off if it prevents people losing their funds. I’m still of the opinion concatenating the base58 encoded dtag onto the end of the original address would have been optimal. That way the user could still clearly see it’s the same address but with a bit of routing info on the end. |
@codetsunami But the two addresses (r.... / X...) will only be during a migration. That will take a year or so, but it's temporary. Once most platforms added support the deprecation of showing the r... address can start. |
@WietseWind you may be right, time will tell |
Like anything, adoption will be key. Consider how BCH migrated to a new address format. |
There are two libraries that do encoding (in JS): These two libraries have the same implementation, but use different parameters from the test. Ripple's homegrown library favors I don't have an opinion on which is better, but I do think it would be great to standardize to reduce user confusion (and selfishly, I'm about to expose this parameter in another library and want to know what to call it). Elliot mentioned that he thinks Do folks have thoughts here? Could we converge these implementations? |
I agree. I will rename |
@WietseWind Here's a PR: xrp-community/xrpl-tagged-address-codec#3 but feel free to ignore it if you have a better way :) |
@intelliot Thanks a lot! I already prepared the changes myself (incl. a little more find/replaces changes in the tests) so I just pushed that one, but I really appreciate it. Updated the site as well. Thanks everybody! |
Note: embedded in |
Abstract
Destination tags provide a way for exchanges, payment processors, corporates or entities which accept incoming payments, escrows, checks and similar transcations to use a single receiving wallet while being able to disambiguate incoming transactions by instructing the senders to include a destination tag.
This draft introduces the concept of a tagged address: an address that contains both the target wallet as well as a destination tag as a single unit.
Motivation
Although flexible, destination tags suffer from several drawbacks.
Communicating a destination tag to users can be a problem for a number of reasons:
This proposal seeks to address this problem by defining a standard format to represent an (address, tag) which:
Limitations
We are not looking to change the on-ledger format; that is, the new style addresses can't be used for fields where an
AccountID
is expected in the binary format. Instead, the packed address will be detected and decoded at higher levels (for example, by the client sofware,ripple-lib
or theRPC
andWebSocket
APIs inrippled
), verified and then split into distinct fields (e.g.sfDestination
andsfDestinationTag
) as appropriate, to assemble the underlying transaction.Philosophy
While we can propose a standard, we need to contend with the fact that, by design, the basics of the protocol (and that includes account addresses) were fixed the moment the ledger was instantiated. While not completely inflexible, account addresses are deeply embedded into the protocol and even if they aren't part of the "core design" changing them would involve a huge amount of pain.
Not all is lost, however and there are things we can do. In this case, we can define a new address style which incorporates the destination tag and software can be understand such packed addresses, improving the UX for users, while intelligently unpacking such addresses into their constituent parts for the underlying system.
Options
Although we have options in developing a new format, including what encoding to use, ideally the resulting addresses will be similar to existing addresses to reduce the likelihood of user confusion as much as possible and, ideally, not requiring developers to implement a new codec.
Given this constrain, we need to use the Base58Check encoding, leaving us with two options:
The advantage of the "loose" format is that a tagged address will precisely match the classic address, up to the tag. The "tight" format results in an address that shares no common prefix with the classic address, except, perhaps, by chance.
The disadvantage of the "loose" format is that a tagged address is more complex to detect, encode and decode.
On balance, we feel that although the "loose" could allow for classic and tagged addresses to co-exist, we believe that the "tight" format is a better choice overall.
Status
This is only a proposal. It is my hope that it will generate discussion between developers, community members and other interested parties, and that we will reach consensus on the way forward.
Comments, criticisms, suggestions and improvements are welcome!
Proposal
Addresses and Destination Tags
For a better introduction to addresses and tags, it may help to reference https://developers.ripple.com/accounts.html.
Existing Format
Currently, an address is generated by base58-encoding (with a checksum) a 21 byte buffer:
[← 1 byte prefix →|← 160 bits of account ID →]
The chosen byte prefix is
TokenType::AccountID
(value 0)Proposed format
In the proposed format, the address and destination tag are combined into a single 30 byte buffer which is then encoded using the familiar Base58Check algorithm as a single unit, using a new two-byte prefix:
[← 2 byte prefix →|← 160 bits of account ID →|← 8 bits of flags →|← 64 bits of tag →]
The tag shall always be encoded as a little endian two's complement 64 bit integer.
Prefix
The standard proposes using different prefixes, making addresses encoded for use on the mainnet have a different initial character than addresses encoded for use on the testnet, making it possible for users and tools to differentiate addresses.
0x05 0x44
X
0x04 0x93
T
It is important to note: an address encoded for mainnet use could still be used on the testnet and vice versa; tools that understand the new format are encouraged to implement protections.
Flags
Adding a flags field allow us to make this format slightly more flexible than it would otherwise be. At this time, only 3 flags are specified, one of which is reserved and may not be used in practice.
NO_TAG
0x00
TAG_32
0x01
TAG_64
0x02
Caution
Exactly one of
NO_TAG
,TAG_32
andTAG_64
MUST be set; implementations should mask of any other fields when checking which of these flags is set.All flag values not explicitly defined are reserved for future extensions and MUST be set to 0. Implementations that encounter flag values that are unknown should return an error and treat the address as invalid.
Encoding Example
Below we present how the classic address
rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf
would be encoded under this spec to include various destination tags. The tag, if any, is on the left most column. The raw bytes, prior to encoding are shown in the second column. Lastly, we show the resulting base58 encoded address.Encoding for Main Net
44AA066C988C712815CC37AF71472B7CBBBD4E2A0A000000000000000000
44AA066C988C712815CC37AF71472B7CBBBD4E2A0A010000000000000000
44AA066C988C712815CC37AF71472B7CBBBD4E2A0A010100000000000000
44AA066C988C712815CC37AF71472B7CBBBD4E2A0A010200000000000000
44AA066C988C712815CC37AF71472B7CBBBD4E2A0A012000000000000000
44AA066C988C712815CC37AF71472B7CBBBD4E2A0A011401000000000000
44AA066C988C712815CC37AF71472B7CBBBD4E2A0A013700010000000000
44AA066C988C712815CC37AF71472B7CBBBD4E2A0A016D12000100000000
44AA066C988C712815CC37AF71472B7CBBBD4E2A0A01FEFFFFFF00000000
44AA066C988C712815CC37AF71472B7CBBBD4E2A0A01FFFFFFFF00000000
Encoding for Testnet
93AA066C988C712815CC37AF71472B7CBBBD4E2A0A000000000000000000
93AA066C988C712815CC37AF71472B7CBBBD4E2A0A010000000000000000
93AA066C988C712815CC37AF71472B7CBBBD4E2A0A010100000000000000
93AA066C988C712815CC37AF71472B7CBBBD4E2A0A010200000000000000
93AA066C988C712815CC37AF71472B7CBBBD4E2A0A012000000000000000
93AA066C988C712815CC37AF71472B7CBBBD4E2A0A011401000000000000
93AA066C988C712815CC37AF71472B7CBBBD4E2A0A013700010000000000
93AA066C988C712815CC37AF71472B7CBBBD4E2A0A016D12000100000000
93AA066C988C712815CC37AF71472B7CBBBD4E2A0A01FEFFFFFF00000000
93AA066C988C712815CC37AF71472B7CBBBD4E2A0A01FFFFFFFF00000000
Advantages
Disadvantages
The primary disadvantage is the untagged address may appear in several places, including things such as trust lines, responses from the
rippled
API endpoints and more and that can be confusing for users.Transaction Example
Consider the following transaction submission:
The server would unpack
XVLhHMPHU98es4dbozjVtdWzVrDjtV8zpDURx7DzBCkrQE7
torGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf
and a destination tag of 2, and process the submission as if it had been:Obviously the server cannot do this when presented with a pre-signed transaction, although assembling and signing a transaction using an unexpanded packed address shouldn't be possible, since the binary encoding of an
AccountID
requires exactly 20 bytes.Third party tools that accept user input should allow users to enter such addresses and transparently expand them prior to signing and/or submitting.
Questions
Below is a list of questions to be addressed as a result of this requirements document:
Should the format include both a source and a destination tag?
Probably not. It's better to simply state that the new format specifies an "address and tag" and to allow such addresses to be used both as a source and as a destination, and to decide the tag's type (source or destination) based on the field.
Can we tweak the encoding so that a packed address shares a common prefix with the actual address?
Not trivially. The Base58 format is quirky and doesn't behave the same way as "power-of-two" encodings, like Base32 or Base16. We could have retained a common prefix by encoding the address and destination tag separately and fusing the two components, but that significantly complicated the decoding process, which is something we sought to avoid.
There's potential for confusion. Can we help?
Users may not understand the semantics of a packed address sufficiently. This means that errors or confusion are possible as a result. Two exchange users might wonder why their deposit addresses are now different. Or one user may ask a friend what the deposit address is and, unknowingly, deposit funds into their friend's account.
The first is obviously not a problem with existing addresses, and the second is less likely to be an issue than these single addresses. The UX of third parties that choose to use the new format will have to make it clear to users that the address is unique for them.
The server could add information to the metadata associated with a transaction to help tools to map addresses. For example, the server could add the following:
Why not BECH32?
The BECH32 format is great and has several advantages over Base58, including speed. We are defining a new address encoding here, so why not just go for that? It's an option, but we decided to be conservative and not require new code to be written or incorporated into servers, clients and libraries.
What happens if someone specifies one of these addresses in the binary format?
The short answer is that they can't. The serialization field only allows exactly 20 bytes, so only the account itself can fit in. This format is only for base58 encoded addresses and is purely a convenience for users.
Should we integrate this natively into the protocol?
No. It would be a huge change and, potentially, breaking one and there aren't any advantages that I can see. There are many risks. Allowing APIs to understand the new format sufficiently to decompose it into its two constituent fields should be sufficient.
The text was updated successfully, but these errors were encountered: