How do I generate a fake but valid protocol hash, like ProtoGenesisGenesisGenesisGenesisGenesisGenesk612im
?
2 Answers
Take
blake2b
hash of arbitrary data.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]))
print(res)
which gives us: b'ProtoGenesisGenesisGenesisGenesisGenesisGenes3pWKfA'
.
PsddFKi32cMJ2qPjf43Qv5GDWLDPZb3T3bF6fLKiF5HtvHNU7aP
is just theb58_check
encoding of the hash of the source code of some economic protocol (like the contents of the directorysrc/proto_003_PsddFKi3/lib_protocol/src
inhttps://gitlab.com/tezos/tezos/tree/mainnet
). However, I think a "fake hash", likeProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK
, is not the hash of something.