Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.Sign up
XLS-5d Standard for Tagged Addresses #6
XRP Ledger Proposed Standard #5 Title: Tagged Addresses Author: Nikolaos D. Bougalis Affiliation: Ripple Created: 2019-05-15
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.
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:
We are not looking to change the on-ledger format; that is, the new style addresses can't be used for fields where an
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.
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.
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!
Addresses and Destination Tags
For a better introduction to addresses and tags, it may help to reference https://developers.ripple.com/accounts.html.
Currently, an address is generated by base58-encoding (with a checksum) a 21 byte buffer:
The chosen byte prefix is
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:
The tag shall always be encoded as a little endian two's complement 64 bit integer.
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.
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.
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.
Exactly one of
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.
Below we present how the classic address
Encoding for Main Net
Encoding for Testnet
The primary disadvantage is the untagged address may appear in several places, including things such as trust lines, responses from the
Consider the following transaction submission:
The server would unpack
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
Third party tools that accept user input should allow users to enter such addresses and transparently expand them prior to signing and/or submitting.
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 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.
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.
Please add others, as necessary.
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
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.
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.
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.
@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.
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:
And it's really hard to pick one;
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
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.
@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.
That's slightly pedantic, but I get your point :) I've actually received emails from people with issues with dest tags cause I've put my email up to help them. I think in some cases the exchanges/counterparties simply didn't have a dispute mechanism in place. In one case, at least as I was told, the "wrong" destination tag routed to another user, who, when the gateway asked him if he would return the funds, claimed that the payment was for a cash transaction. The gateway didn't know what to do, and which jurisdiction should be involved and told the "loser" of the funds to ask their lawyer. I think in that case, the amount in question was around $7,000.
If the issue is that the user sent to an old "used" destination tag, then I'm not sure how a new format would help them.
If the gateway reuses destination tags after a period of time (e.g. 24 hours or 7 days or whatever) then having an expiry encoded in the address would help.
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.
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 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.
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.