Stacks token address

Hey all,

In order to avoid confusion, we’re going to use a custom address encoding for Stacks tokens. Specifically, our user research implies the following requirements:

  • Does NOT use the base58 alphabet (this is used by Bitcoin and a lot of altcoins)
  • Does NOT use a raw hex string–a checksum is required
  • Must use an alphabet that does not permit homoglyph attacks (i.e. l and 1 cannot both be allowed)
  • Must be easy to select in Web forms and mobile–i.e. through double-click or tap-and-hold
  • Must be easy for wallet authors to implement

The best we’ve come up with is to use the same address scheme for Bitcoin, but use the z-base-32 alphabet to encode it. Specifically, a Stacks address is a version byte, the hash160 of the user’s public key, and a 4-byte double-sha256 checksum over the version byte and hash160. An example of this scheme (and surrounding discussion) can be found here.

The address would start with the caplitalized z-base-32 letter that encodes the version, in order to distinguish it from a random z-base-32 string (note that the z-base-32 alphabet does not have any capital letters). The version bytes we’d use would give a hint as to what kind of address it is (i.e. testnet vs mainnet, single-key vs multisig).

Here is an example of what this would look like:

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

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

version: 22 (0x16)
checksum(‘16’, ‘a46ff88886c2ef9762d970b4d2c63678835bd39d’): 71b4ba47
address: Sn1g96reo5bq9f5n5famjwsgg3hegs6uuia5jq18

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

version: 11 (0x0b)
checksum(‘0b’, ‘a46ff88886c2ef9762d970b4d2c63678835bd39d’): 61ab97bb
address: Mn1g96reo5bq9f5n5famjwsgg3hegs6uuio4zf75

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

version: 17 (0x11)
checksum(‘11’ + ‘a46ff88886c2ef9762d970b4d2c63678835bd39d’): bf29c230
address: Tn1g96reo5bq9f5n5famjwsgg3hegs6uus91uoto

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

version: 2 (0x02)
checksum(‘02’ + ‘a46ff88886c2ef9762d970b4d2c63678835bd39d’): 2f458b49
address: Nn1g96reo5bq9f5n5famjwsgg3hegs6uuwzwmn4j

Let us know your thoughts! We’re looking to make a decision on this by Monday 2 July.

1 Like

Adding an update: we’re also considering the Crockford base32 alphabet, since it can be written in upper or lower case without homoglyphs (and would be easier to use on mobile). The github issue for this has also been updated (https://github.com/blockstack/blockstack-core/issues/832)

+1 to Crockford given the upper/lower case property (good to not differentiate based on that).

I am debating if using:

  • SSn1g96reo5bq9f5n5famjwsgg3hegs6uuia5jq18
  • SMn1g96reo5bq9f5n5famjwsgg3hegs6uuio4zf75

or some other variation makes sense. Basically, it’d be nice to have the property that Stacks addresses always start with S.

Agreed-- can we just always prepend an S to the address, and just remove it before decoding/checksumming?

1 Like

Yeah, let’s do this. All Stacks addresses start with S no matter what. The version byte will be the second character, and give a hint to what kind of address this is (testnet vs mainnet, p2sh vs p2pkh).

1 Like

Great – and we should probably avoid the repeated S in mainnet pubkeyhash prefixes by using a different version byte.

How about P instead?

1 Like

P sounds good to me.

Now implemented here: https://github.com/jcnelson/c32check

1 Like

I might open a PR on that with a bunch of test data generated from another Crockford 32 library.

1 Like