How do I generate a fake but valid protocol hash, like ProtoGenesisGenesisGenesisGenesisGenesisGenesk612im?

  • i think you might as well simply ask the more general question: "how is the protocol hash computed" because it has never been explained here in detail. From there you should be able to try generate vanity protocols hashes if you like ;)
    – Ezy
    Commented Feb 23, 2019 at 20:25
  • 1
    I think a "real" protocol hash, like PsddFKi32cMJ2qPjf43Qv5GDWLDPZb3T3bF6fLKiF5HtvHNU7aP is just the b58_check encoding of the hash of the source code of some economic protocol (like the contents of the directory src/proto_003_PsddFKi3/lib_protocol/src in https://gitlab.com/tezos/tezos/tree/mainnet). However, I think a "fake hash", like ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK, is not the hash of something.
    – Eugen
    Commented Feb 25, 2019 at 9:17

2 Answers 2

  1. Take blake2b hash of arbitrary data.

  2. Prepend \x02\xaa and base58 encode it with checksum.

Example in Python:

from pytezos.encoding import base58_encode
from pytezos.crypto import blake2b_32

base58_encode(blake2b_32('test').digest(), b'P')
>>> b'PsqEZzKWvmWY29kV6oJZhWDNz9FMmYDjV3S7c496zMuAGDYAF7e'

A "Tezos protocol hash" like PsqEZzKWvmWY29kV6oJZhWDNz9FMmYDjV3S7c496zMuAGDYAF7e is the Base58Check encoding of the hash of some protocol code.

The Base58Check encoding of some data is obtained as follows:

  base58encode(prefix + data + checksum)

where prefix is some fixed bytestring used to identify the type of data we are encoding, data is the bytestring we are encoding, and checksum are the last 4 bytes of SHA256(SHA256(prefix+data)) (and + is bytestring concatenation).

For a "real" protocol hash, data is the Blake2B hash (on 32 bytes) of the protocol code, and prefix is chosen such that the Base58Check encoding starts with the letter P. It turns out that this prefix is "\002\170" ("\x02\xaa"), see the Prefix submodule of the Base58 module.

A "fake" protocol hash is such that it does not represent any protocol code, instead it is just a valid Base58Check string. So data is the empty bytestring, and what we want is to find the bytestring prefix such the encoding starts with some meaningful target prefix like ProtoGenesisGenesisGenesisGenesisGenesisGenes. To this end the Python script b58_prefix.py comes to the rescue:

$ scripts/b58_prefix.py ProtoGenesisGenesisGenesisGenesisGenesisGenes 0
51 78975543388164909405054148723984031781676975010405372310033317301022658928601531 [2L, 170L, 11L, 205L, 127L, 252L, 160L, 63L, 87L, 227L, 132L, 83L, 240L, 211L, 232L, 76L, 48L, 36L, 3L, 192L, 83L, 87L, 68L, 139L, 76L, 45L, 174L, 248L, 179L, 168L, 190L, 60L, 105L, 187L]

We invoke it with the desired target prefix and the length of the payload (this is 0 as the payload is empty). The list represents the desired prefix. Finally, we just need to encode this prefix:

import base58

def tb(l):
    return b''.join(map(lambda x: x.to_bytes(1, 'big'), l))

res = base58.b58encode_check(tb([2, 170, 11, 205, 127, 252, 160, 63, 87, 227, 132, 83, 240, 211, 232, 76, 48, 36, 3, 192, 83, 87, 68, 139, 76, 45, 174, 248, 179, 168, 190, 60, 105, 187]))


which gives us: b'ProtoGenesisGenesisGenesisGenesisGenesisGenes3pWKfA'.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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