stacks-network / stacks-core

The Stacks blockchain implementation
https://docs.stacks.co
GNU General Public License v3.0
3.01k stars 672 forks source link

Unique Stacks address format #832

Closed larrysalibra closed 6 years ago

larrysalibra commented 6 years ago

Moved from: https://github.com/blockstack/blockstack-core/issues/822#issuecomment-391680586

I think from a product and user experience perspective it makes more sense to use different address formats for the different token types.

There are a number of reasons for this. One reason is that without its "own" format like ethereum has it's own 0x format, it doesn't seem like a full blown separate coin.

Another reason is to avoid user confusion. A bitcoin address is a bitcoin address. If i want to ask someone for the account to which they'd like to send me Stacks, do I ask them for a bitcoin address? How can someone looking at the string determine if the wallet software that generated supports stacks or only bitcoin?

larrysalibra commented 6 years ago

@jcnelson wrote

Ah, I see what you mean. I'm definitely in favor of making the Stacks account identifier Stacks-specific. I agree that we should use a format that does not get confused with an existing cryptocurrency---the account identifier format should be Stacks-specific.

That being said, I have no strong opinions on what exactly the format will be. Do you have any suggestions? The only thing that might have been a good idea but we cannot do is change the address version to make the first character S, since we're already using those for subdomain addresses in DIDs. However, anything else is fine with me.

larrysalibra commented 6 years ago

@anastik wrote

What about using a “$” at the front of each address? It might give off the wrong impression, but it still kind of uses the “S” and it easily denotes that it’s financial in nature. Could even be “$tx” or something along those lines.

larrysalibra commented 6 years ago

@jcnelson wrote

@Anastik Nice idea, but we want to avoid country-specific money identifiers. $ is pretty US-centric.

shea256 commented 6 years ago

That being said, I have no strong opinions on what exactly the format will be. Do you have any suggestions? The only thing that might have been a good idea but we cannot do is change the address version to make the first character S, since we're already using those for subdomain addresses in DIDs. However, anything else is fine with me.

Possible to us "S" for both? Is there any reason not to? We just don't want the same character as Bitcoin addresses right?

jcnelson commented 6 years ago

Can use "S" for both. The only point of confusion is that we already use S-encoded addresses for subdomain DIDs. Example:

$ python
Python 2.7.14 (default, Dec 14 2017, 15:51:29)
[GCC 6.4.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import blockstack
>>> blockstack.lib.client.get_name_DID('jude.statism.id', hostport='http://localhost:6264')
u'did:stack:v0:SSXMcDiCZ7yFSQSUj7mWzmDcdwYhq97p2i-0'
>>> blockstack.lib.client.resolve_DID('did:stack:v0:SSXMcDiCZ7yFSQSUj7mWzmDcdwYhq97p2i-0', hostport='http://localhost:6264')
{'public_key': '020fadbbcea0ff3b05f03195b41cd991d7a0af8bd38559943aec99cbdaf0b22cc8'}

What do you think of having a prefix in front of the address? Examples:

kantai commented 6 years ago

One important thing to keep in mind here is that this is going to interact with any wallet initialization that participants in the genesis block are going to be doing. So I think it's important for @yknl to see and weigh in on this.

jcnelson commented 6 years ago

If we don't want to look like Bitcoin, we should avoid base58check encoding.

kantai commented 6 years ago

Base58 Check Encoding has some pretty well thought out benefits though (doesn't use ambiguous characters, encodes checksums and zero-padding effectively). Getting those last two right can be unfortunately kind of bug-prone and I'd hate to introduce a bug here.

Another option is to use the S-prefixed base58 check address, but do something purely to the display like prefacing with 0- and throwing a hyphen in at character 5:

0-SSXM-cDiCZ7yFSQSUj7mWzmDcdwYhq97p2i

Makes it look very different from a bitcoin address. I have nothing to add from a brand awareness or marketability perspective, but I think those are probably important perspectives to consider.

yknl commented 6 years ago

One thing about having hyphens or punctuation characters is that you can't double click it to select the whole string.

jcnelson commented 6 years ago

Let me see if I can summarize here:

Requirements

Prefix Annotations

To make it unambiguous, I highly recommend a short prefix be appended to addresses. This seems to have worked well for Ethereum, for example---a long hex string starting with 0x is assumed to be an Ethereum address.

The choice of prefix must not conflict with the encoding alphabet letters.

Examples

Let 395f3643cea07ec4eec73b4d9a973dcce56b9bf1 be the account's hexadecimal representation.

Let the version be 00.

Then, the checksum is double_sha256(version + '395f3643cea07ec4eec73b4d9a973dcce56b9bf1')[:8] = '435e3bc5'.

So, we'll really be encoding 00395f3643cea07ec4eec73b4d9a973dcce56b9bf1435e3bc5 as our example.

Hex (Base 16)

Base32

Z-Base-32

Cockford Base-32

Base58 (Bitcoin)

Base64 (no padding)

yknl commented 6 years ago

My vote is for one of the Base32 encodings plus a s prefix. Also maybe a different prefix for testnet addresses?

larrysalibra commented 6 years ago

I like the Base32 ones as well.

jcnelson commented 6 years ago

So...use z-base-32 encoding with a s prefix for mainnet and a t prefix for testnet? Does that work for everyone?

yknl commented 6 years ago

sounds good to me

jcnelson commented 6 years ago

Okay, here's what I'm going with:

An address of compressed public key P is:

addr(P) = version + RIPEMD160(SHA256(P)) + checksum(version, RIPEMD160(SHA256(P))

where checksum(version, pubkeyhash) = SHA256(SHA256(version + pubkeyhash))[:4].

Example

Private key: 35ad2ef1f303dcbe74c2714ac133031e34db7c7529d072b741537030584cb6c401 Public key: 035a5235220903d5f89c2d19069c08c31622253422baba80dcb26f43619ca5e248 RIPEMD160(SHA256(public key)): a46ff88886c2ef9762d970b4d2c63678835bd39d

Mainnet pay-to-pubkey-hash (starts with s):

Mainnet pay-to-script-hash (starts with m)

Testnet pay-to-pubkey-hash (starts with t)

Testnet pay-to-script-hash (starts with n)

Please :+1: this if you agree.

stackatron commented 6 years ago

I'm fine with this latest iteration.

Looking over the whole thread, I did see the value in the S– options. I kind of see this as a branding opportunity while people transact using our token. And a safeguard against confusion as people make transfers between wallets and exchanges, which is a real problem in everyday use. Re selecting—on mac 3 clicks will select the entire string including any dashes.

larrysalibra commented 6 years ago

Looking over the whole thread, I did see the value in the S– options. I kind of see this as a branding opportunity while people transact using our token.

+1 to this. I don't think they look unique enough to be instantly recognizable as blockstack addresses like 0x addresses are instantly recognizable as ethereum addresses.

We probably shouldn't have people copying and selecting addresses anyways. The selecting the whole string issue probably shouldnt' be weighted as much as branding.

@jcnelson are we limited to only ascii characters to put between S and the rest of the address?

Adding a thumbs down vote until we've re-visited the branding issue. I'm not strongly against, but it seems like we should take advantage of the opportunity if possible.

jcnelson commented 6 years ago

We probably shouldn't have people copying and selecting addresses anyways. The selecting the whole string issue probably shouldnt' be weighted as much as branding.

I strongly disagree. People will copy/paste addresses into web forms and the CLI all the time, no matter what we tell them. We should select an address format that is amenable to double-click-select (desktop) or tap-hold-select (mobile). The convenience of being able to do this significantly outweighs the extra branding boost we may or may not get by having a - in the address format.

@jcnelson are we limited to only ascii characters to put between S and the rest of the address?

I'm using the z-base-32 alphabet to encode addresses. We can have non-z-base-32 characters as a prefix, but I must insist that whatever prefix we use, it preserves the ability to easily select and copy addresses.

larrysalibra commented 6 years ago

People will copy/paste addresses into web forms and the CLI all the time, no matter what we tell them.

This is good point. Thinking more about it, I'm also sold on the value of this.

the extra branding boost we may or may not get by having a

I just think there's an opportunity to have a uniquely blockstack address and I was surprised by how they looked less unique than I expected.

The reason I asked about non-ascii characters was that I thinking about including a symbol or emoji character. That would add the trade off of making it hard to type. Thoughts on that?

--

What about capitalizing the first letter?

Example (capital first letter)

Private key: 35ad2ef1f303dcbe74c2714ac133031e34db7c7529d072b741537030584cb6c401 Public key: 035a5235220903d5f89c2d19069c08c31622253422baba80dcb26f43619ca5e248 RIPEMD160(SHA256(public key)): a46ff88886c2ef9762d970b4d2c63678835bd39d

Mainnet pay-to-pubkey-hash (starts with S):

Mainnet pay-to-script-hash (starts with M)

Testnet pay-to-pubkey-hash (starts with T)

Testnet pay-to-script-hash (starts with N)

jcnelson commented 6 years ago

That's fine by me.

jcnelson commented 6 years ago

I have a z32check encoding library here, if you all want to take a look: https://github.com/jcnelson/z32check

jcnelson commented 6 years ago

Forum post: https://forum.blockstack.org/t/stacks-token-address/5612

Let's get this closed by 2 July.

jcnelson commented 6 years ago

@shea256 raised an interesting point that one advantage of the Cockford base32 alphabet is that it can be written in either upper or lower case without losing its meaning and without introducing homoglyphs. This is a UX win because it makes it easier to communicate addresses, especially when typing is difficult. z-base-32 does not have this property, since it includes both i and 1.

What do you all think about Cockford base32? @larrysalibra @kantai @yknl

yknl commented 6 years ago

I don't see any downsides compared to zbase32, sounds good to me 👍

kantai commented 6 years ago

Also works for me

jcnelson commented 6 years ago

New repo for address encoding: https://github.com/jcnelson/c32check

larrysalibra commented 6 years ago

Works for me too!

jcnelson commented 6 years ago

Got it shipped. Thanks everyone!