7

This is not a duplicate of What is the most efficient way to store bitcoin addresses in a database? but it's the same question except I need a segwit answer.

Let's say I wanted to store every standard BTC address in an SQL database. The most space efficient way is to extract the HASH160 address by converting to base58 then slicing away the checksum. This will allow you to store a BTC address in 20 bytes.

Until segwit blocks come.

Is there a way to get to the hash160 address from: bc1q34aq5drpuwy3wgl9lhup9892qp6svr8ldzyy7c

If not, could someone tell me the most space efficient way to store this address in a database?

I have no need to convert it back to original string, but only ensure its identity.

Thank you

  • 2
    A popular block explorer converting addresses into hash160's in their database resulted in funds loss, since their service erroneously reported the same funds being paid to both p2pkh and p2sh addresses. Make very sure what you do is fit for purpose... – G. Maxwell Sep 25 at 18:43
  • Thank you, it's just for a home machine learning project. Not a mission critical security application. – Roderick Obrist Oct 16 at 5:19
8

Is there a way to get to the hash160 address from bc1q34aq5drpuwy3wgl9lhup9892qp6svr8ldzyy7c

Yes, you could use the reference implementations in various languages to encode and decode a bech32 address. For example, I have decoded the sample address you mentioned in the question, bc1q34aq5drpuwy3wgl9lhup9892qp6svr8ldzyy7c, using python below. The decode function gives us the witness version (0 in this case) and a byte array.

import bech32

address = "bc1q34aq5drpuwy3wgl9lhup9892qp6svr8ldzyy7c"
address_decoded = bech32.decode("bc", address)

address_decoded  # a tuple containing witness version and bytearray of the address
>>> (0, [141, 122, 10, 52, 97, 227, 137, 23, 35, 229, 253, 248, 18, 156, 170, 0, 117, 6, 12, 255])

bytes(address_decoded[1])
>>> b'\x8dz\n4a\xe3\x89\x17#\xe5\xfd\xf8\x12\x9c\xaa\x00u\x06\x0c\xff'  

Couple of points to note:

  • The address you have mentioned here is a P2WPKH and has a length 20 bytes. However, P2WSH addresses are 32 bytes (they also begin with "bc1...") as we take the SHA256 of the witnessScript instead of HASH160.
  • Although version 0 addresses (P2PKH, P2WSH) will have a data payload of 1+20 or 1+32 bytes, BIP173 allows up to 40 bytes in a witness program, for a total of 1+40 bytes.
  • 1
    Note that although version 0 addresses will have a data payload of 1+20 or 1+32 bytes, BIP173 allows up to 40 bytes in a witness program, for a total of 1+40. – Raghav Sood Sep 25 at 6:24
  • @RaghavSood Thanks. I have incorporated that in my answer. – Ugam Kamat Sep 25 at 10:27
2

As per BIP 173, the data part consists of:

The data-part values:
1 byte: the witness version
A conversion of the 2-to-40-byte witness program (as defined by BIP141) to base32:
Start with the bits of the witness program, most significant bit per byte first.
Re-arrange those bits into groups of 5, and pad with zeroes at the end if needed.
Translate those bits to characters using the table above.

The value itself is simply the byte data encoded with bech32's encoding system, which is also outlined in BIP 173.

Thus, you need to store up to 41 bytes per address, if you know that all your addresses have the same human readable portion. If not, you will need an additional byte or two to store a reference to which human readable part that address uses (if that information is relevant to your usecase - the 41 bytes from the data portion may be enough, if all you want is a list of used Bitcoin addresses, for example).

The human readable part is usually fixed for a given network or address family, and the separator is always 1

protected by Community Oct 2 at 8:13

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

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