Skip to content

CashAddr encoding

CashAddr encoding is an address format used in Nexa. This is a Base32 encoding format. The goal of the encoding is to make it easier to copy and to share information, by using a QR code for instance.

A Cash Address consists of:

  • A prefix which is human-readable.
  • A separator (:).
  • A Base32 payload which contains a version byte and the data (or hash).
  • A Base32 checksum.

This format reuses the work done for Bech32 (see BIP173) and is similar in some aspects, but improves on others. See the original specification for more details.

Prefix

The prefix is a human-readable part of the address which indicates the network on which the addess is valid, or the metaprotocol used. It can only contain ASCII characters.

There are 3 prefixes used in Bitcoin Cash to indicate the network:

Network Prefix
Mainnet nexa
Testnet nexatest
Regtest nexareg

The prefix can also indicate for which metaprotocol the address must be used.

The prefix is always followed by the separator :.

When presented to users, the prefix and the separator may be omitted as it is part of the checksum computation. Due to this checksum difference, an address (without the prefix) on one blockchain is extremely unlikely to be a valid address on a different one.

Address Lengths

Nexa cashaddr encoding has no restriction on address length.

Base32

CashAddr uses Base32 to encode information. The symbols used in CashAddr Base32 are the lowercase alphanumeric characters excluding 1, b, i, and o. Uppercase characters are also valid to enable efficient QR code encoding (see spec). However, any mixture of lowercase and uppercase characters must be rejected.

Base32 alphabet:

qpzry9x8gf2tvdw0s3jn54khce6mua7l

Base32 symbol chart:

Value Character Value Character
0 q 16 s
1 p 17 3
2 z 18 j
3 r 19 n
4 y 20 5
5 9 21 4
6 x 22 k
7 8 23 h
8 g 24 c
9 f 25 e
10 2 26 6
11 t 27 m
12 v 28 u
13 d 29 a
14 w 30 7
15 0 31 l

Checksum

The checksum is a 40 bits Bose–Chaudhuri–Hocquenghem code (BCH) code defined over the finite field GF(2^5). It ensures the detection of up to 6 errors in the address and 8 in a row. Combined with the length check, this provides very strong guarantee against errors.

The checksum is computed by the following polymod function (written in Python):

def polymod(values):
        c = 1
        for d in values:
            c0 = c >> 35
            c = ((c & 0x07ffffffff) << 5) ^ d
            if (c0 & 0x01):
                c ^= 0x98f2bc8e61
            if (c0 & 0x02):
                c ^= 0x79b76d99e2
            if (c0 & 0x04):
                c ^= 0xf33e5fb3c4
            if (c0 & 0x08):
                c ^= 0xae2eabe2a8
            if (c0 & 0x10):
                c ^= 0x1e4f43e470
        return c ^ 1

where & is the bitwise AND operator, ^ is the bitwise XOR operator, and >> is the bitwise right shift.

Version bytes

The length portion (lowest 3 bits) of the version byte as defined in the cashaddr specification is obsolete, but Nexa version bytes set this value to 0 for now.

The version byte for script template address types, the first byte MUST be 152. This begins each address with "n", and defines the contents as specified below. The version byte for group (token) identifiers the first byte MUST be 88. This begins each address with "t". The version byte for legacy (pay-to-pubkey-hash) address types, the first byte MUST be 0. This is as defined in the CashAddr spec.

Address Contents

Script Templates

The serialized output locking data "script".

Group Identifier

The 256 bit group identifier, as created during the group genesis transaction.

Pay-to-public-key hash

the 160 bit hash of the public key (the same as Bitcoin/Bitcoin Cash).

Encoding a Nexa address

To encode an address with CashAddr, follow the steps described below:

  1. Take the address data, which is the hash of a public key (P2PKH) or group, or serialized output template (script templates).

  2. Concatenate the version byte and the data bytes together (bytewise):

    payload = version || data
    
  3. Divide the payload into chunks of 5 bits. The payload is padded to the right with zero bits to complete any unfinished chunk at the end.

  4. Compute the checksum by applying polymod to the following values:

    a. The lower 5 bits of each character of the prefix. For letters, this corresponds to their position in the alphabet.

    b. A zero for the separator (5 zero bits).

    c. The payload.

    d. Eight zeros as a template for the checksum.

  5. Encode each chunk of the payload and each chunk of the checksum with Base32.

Examples

Ungrouped Pay-to-public-key-template (P2PKT) Form

OP_0 # No group OP_1 # Well known template 1 PUSH Hash160(Script(PUSH pubkey)) [Optional: TBD additional data (do not rely on the size to identify this address form)]

Example
nexa:nqtsq5g5w6syq5aa5z5ghkj3w7ux59wrk204txrn64e2gs92

Grouped, Unspecified Token Amount, Pay-to-public-key-template (GP2PKT) Form

PUSH GroupId OP_0 # Unspecified token amount OP_1 # Well known template 1
PUSH Hash160(Script(PUSH pubkey)) [Optional: TBD additional data (do not rely on the size to identify this address form)]

Example
nexa:nqazqy3uqsp4j0zyyufqzy65qc2u9vvm2jthyqgzqvzq2ps8pqys5zcvqgqqq5g5w6syq5aa5z5ghkj3w7ux59wrk204txrn92xzqzsu

Ungrouped Pay-To-Contract-Args-Template (P2CAT) Form

OP_0 # No group
PUSH Hash160/256(Script(... your contract...)) PUSH Hash160/256(Script(PUSH your args ...)) [Optional: PUSH visible args]... [Optional: TBD additional data]...

Example
nexa:nq4sq9rk5pq980dq4z9a55thhp4ptsajna2esuc5zg7qgq6e83zzwyspzd2qv9wzkxd4f9mjwp6hsdfn

Grouped, Pay-To-Contract-Args-Template (GP2CAT) Form

PUSH GroupId
OP_0 # Unspecified token amount
PUSH Hash160/256(Script(... your contract...))
PUSH Hash160/256(Script(PUSH your args ...))
[Optional: PUSH visible args]...
[Optional: TBD additional data]...

Example
nexa:np9sq9rk5pq980dq4z9a55thhp4ptsajna2esuc5zg7qgq6e83zzwyspzd2qv9wzkxd4f9mjzg7qgq6e83zzwyspzd2qv9wzkxd4f9mjqypqxpq9qcrsszg2pvxq3p2q9kaa

Ungrouped Pay-To-Contract-Template (P2CT) Form (no args)

OP_0 # No group
PUSH Hash160/256(Script(... your contract...)) OP_0 # No args [Optional: PUSH visible args]... [Optional: TBD additional data]...

Example
nexa:nqtsq9rk5pq980dq4z9a55thhp4ptsajna2esucqqj42vk56

Bitcoin Cash (or similar P2PKH for Nexa)

The steps to encode a P2PKH address which is valid on the Bitcoin Cash main network are:

  1. Take the address data, i.e., the 20-byte hash of the public key:

    211b74ca4686f81efda5641767fc84ef16dafe0b
    
  2. Concatenate the version byte (here 0x00) and the data bytes together to get the payload:

    00211b74ca4686f81efda5641767fc84ef16dafe0b
    
    2. Divide the payload into chunks of 5 bits. In this example, the payload is 168-bit long; therefore, it is padded to the right with 2 zero bits to complete the last chunk. The resulting chunks are:

    [ 0, 0, 16, 17, 22, 29, 6, 10, 8, 26, 3, 15, 16, 7, 23, 29, 20, 21, 18, 1, 14, 25, 31, 28, 16, 19, 23, 17, 13, 22, 23, 30, 1, 12 ]
    
  3. Compute the checksum by applying polymod to the concatenation of:

    a. The lower 5 bits of each character of the prefix bitcoincash:

    [ 2, 9, 20, 3, 15, 9, 14, 3, 1, 19, 8 ]
    

    b. A zero for the separator:

    [ 0 ]
    

    c. The payload chunks:

    [ 0, 0, 16, 17, 22, 29, 6, 10, 8, 26, 3, 15, 16, 7, 23, 29, 20, 21, 18, 1, 14, 25, 31, 28, 16, 19, 23, 17, 13, 22, 23, 30, 1, 12 ]
    

    d. The template of the checksum:

    [ 0, 0, 0, 0, 0, 0, 0, 0 ]
    

    The checksum is:

    [ 28, 10, 17, 3, 2, 3, 3, 28 ]
    
  4. Encoded with Base32, the payload and the checksum are, respectively, qqs3kax2g6r0s8ha54jpwelusnh3dkh7pv and u23rzrru. The resulting address is:

    bitcoincash:qqs3kax2g6r0s8ha54jpwelusnh3dkh7pvu23rzrru