I'm trying to write address validation in Python. According to the docs, Shelley addresses are encoded with bech32 and the first byte of the payload consists of header_type (4 bits) and network_tag (4 bits).

So, let's consider the following address: addr1w8phkx6acpnf78fuvxn0mkew3l0fd058hzquvz7w36x4gtcyjy7wx

In [2]: bech32.bech32_decode("addr1w8phkx6acpnf78fuvxn0mkew3l0fd058hzquvz7w36x4gtcyjy7wx")

The first byte of the payload is 14, which would mean network_tag = 14 and header_type = 0. However, (a) the HRP doesn't contain the _test suffix and (b) cardano-address reports different network tag than my result does:

$ echo addr1w8phkx6acpnf78fuvxn0mkew3l0fd058hzquvz7w36x4gtcyjy7wx | cardano-address address inspect
    "spending_shared_hash": "c37b1b5dc0669f1d3c61a6fddb2e8fde96be87b881c60bce8e8d542f",
    "stake_shared_hash_bech32": "stake_shared_vkh1cda3khwqv60360rp5m7akt50m6ttapacs8rqhn5w342z7p6v69g",
    "address_style": "Shelley",
    "network_tag": 1,
    "spending_shared_hash_bech32": "addr_shared_vkh1cda3khwqv60360rp5m7akt50m6ttapacs8rqhn5w342z70dxhec",
    "stake_reference": "none",
    "stake_shared_hash": "c37b1b5dc0669f1d3c61a6fddb2e8fde96be87b881c60bce8e8d542f"

I guess I'm making some stupid mistake, but where?


I would use the bech32 decoder tool available here: https://github.com/input-output-hk/bech32

You can also find it in Daedalus in the binaries folder for your platform.

$ bech32 <<< addr1w8phkx6acpnf78fuvxn0mkew3l0fd058hzquvz7w36x4gtcyjy7wx

This outputs the address in a hex format which is easier to understand as each 2 hex characters are one byte.

7# at the start means that it's a smart contract address, I believe. The 1 in 71 means a mainnet address. 70 would be a testnet address.

More info about addresses can be found here: https://github.com/cardano-foundation/CIPs/blob/master/CIP-0019/CIP-0019.md

  • 1
    OK, it seems the bech32 implementations differ. Thank you for pointing out the IOHK source. Somehow I missed it.
    – emesik
    Jul 2 at 9:38

The problem stems from bech32 being a base5 encoding, which means that one character of address representation encodes only 5 bits of the actual address data.

The bech32_decode function from Python Reference Implementation leaves the decoded data as it is: every byte may have only 5 youngest bits used. Meanwhile the Cardano tools use converted notation, where bits are shifted left and "packed".

In the PRI you may add another step to get the packed data into payload var:

hrp, _payload32 = bech32_decode(address)
payload = convertbits(_payload32, 5, 8, False)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.