How to submit a Tezos Protocol Proposal

Nicolas Ochem
The Aleph
Published in
6 min readJan 27, 2023
The Seat of Justice in the Parliament of Paris in 1723 licensed CC BY 2.0

Any Tezos baker can submit a proposal. As per the rules of Tezos on-chain governance, any proposal approved by a 80% supermajority of the bakers will become the chain’s next protocol.

However, there is a convention in Tezos where proposals have been named after cities, in alphabetical order.

Every proposal is identified by its hash. Since the Babylon proposal in 2019, every proposal hash has been a vanity hash, where the first few letters of the hash match the city name of the protocol.

This guide explains how to make a simple change to an existing proposal and create such a vanity hash. It assumes some familiarity with the command line interface, git, the pull request workflow, source code editing, and building software from source.

Write your Proposal

A simple protocol change consists of minting new Tez and allocating them to an address: this is typically done to reward an ecosystem participant for a positive contribution, in software or otherwise.

Below we explain how to perform such a change.

There are other easy-ish protocol changes you can submit to governance. See for example How to Change the Liquidity Baking Asset Pair by Sophia Gold.

All Tezos proposals that ever were on Tezos mainnet are stored in the Octez repository, specifically in the src/proto_*/lib_protocol folders. See for example the Lima protocol.

Below we will assume that the protocol is already snapshotted. “Snapshotting” a protocol is the process where a Tezos protocol moves from the main development folder (src/proto_alpha) to go to its own folder (src/proto_016_PtMumbai) for safekeeping. The snapshotting process itself is out of scope for this guide.

Specifically, we will modify the Mumbai protocol, located in src/proto_016_PtMumbai.

Clone the repository:

git clone https://gitlab.com/tezos/tezos.git
cd tezos

Inside the protocol folder src/proto_016_PtMumbai/lib_protocol , the init_storage.ml file contains a helper function called invoice_contract that you must uncomment. In OCaml, comments start with (* and end with *).

Delete these 2 lines before the function:

(*
To add invoices, you can use a helper function like this one:

and the one line after the invoice_contract function:

*)

Now that the invoice_contract function is uncommented, you may call it in the prepare_first_block function.

This function acts differently based on the previous_protocol. For example, on mainnet, the Mumbai protocol comes after Lima, therefore you must target the case statement that deals with upgrades from Lima.

Instead of just returning the context with return (ctxt, [])) , our function must invoke the just uncommentedinvoice_contract function, passing as parameters the amount in mutez (one millionth of a tez) and the public key hash (starting with tz) of the address to credit.

Add the following at the end of the case statement. This example mints and credits 100,000 tez to the address tz3RDC3…VB1CxD9:

      invoice_contract
ctxt
~address:"tz3RDC3Jdn4j15J7bBHZd29EUee9gVB1CxD9"
~amount_mutez:100_000_000_000L
>>= fun (ctxt, balance_updates) -> return (ctxt, balance_updates))

For more examples, you can browse the commits associated with the invoices included in past proposals:

Compile

After changing the protocol code, check that it still compiles by building from source.

See the OpenTezos guide on how to build Octez from source for more details.

After a succesful compilation, you should see binaries such as octez-node and octez-protocol-compiler in your working directory.

Did it compile without error? Good. Otherwise, make sure that it works with the master branch, and understand which of your modifications caused the breakage. Don’t hesitate to reach out to the community for help.

Create a Vanity Hash

Creating a vanity hash consists of editing a commented random string inside the protocol proposal and hashing it over and over, until the resulting hash starts with the string that you expect.

We present 2 methods: local and cloud. The cloud method will find hashes faster but is more complex to setup.

Download your protocol binary

Your modifications will change the protocol hash. Calculate the new hash with the octez-protocol-compiler command:

$ ./octez-protocol-compiler -hash-only src/proto_016_*/lib_protocol
Psm5KsjAm73vQsdMpBfkTm9YmBjx3DHznR3HHhbnpLkpjCkf2WX

To find a better hash, let’s first download your protocol in binary format.

In the file src/proto_016_PtMumbai/lib_protocol/TEZOS_PROTOCOL , replace the original protocol with the new hash you just calculated. Compile again with make. Then run Octez in private mode:

./octez-node run --synchronisation-threshold 0 --connections 0 --rpc-addr localhost

Download your new protocol with the curl command and store it in the mumbai_v file:

curl -H "Accept: application/octet-stream" http://localhost:8732/protocols/Psm5KsjAm73vQsdMpBfkTm9YmBjx3DHznR3HHhbnpLkpjCkf2WX > mumbai_v

Calculate the hash locally

This method will calculate the hash on your computer.

You will find a 4-character hash such as PtMumb in a minute. However, be advised that 6-character hashes such as PtMumbai will take several hours on a single computer. For faster searches, please use the cloud method below.

Download and unpack the tz-proto-vanity binary.

Then run:

./tz-proto-vanity mumbai_v PtMumb

After some time you will see results:

$ ./tz-proto-vanity mumbai_v PtMumb
Looking for vanity hash PtMumb for mumbai_v using 8 threads and vanity set {"PtMumb"}
Current hash: Psm5KsjAm73vQsdMpBfkTm9YmBjx3DHznR3HHhbnpLkpjCkf2WX
┌────────────────────────────────────────────
2│ (* Vanity nonce: 7631808252943472 *)
│ └> PtMumbFt3sHAYrrnmoR7CMvCTbynQ6oFm7R6zcNCnLUWouAQhx9
│ found in: 9s (393982 attempts)
│ found so far: 1 (6.67/minute)
│ elapsed: 9s/9s
│ total found: 1 (6.67/minute)
└────────────────────────────────────────────

The vanity nonce is 7631808252943472. See the section “Submit your proposal” below for instructions how to put it in your code and submit.

Calculate the hash in a Kubernetes cluster

For faster results, it is possible to leverage the cloud.

It works like this:

  • create a file bucket (Amazon S3 or equivalent) with your protocol in it
  • launch a Kubernetes cluster with several powerful machines
  • install the tezos-proto-cruncher helm chart
  • wait
  • when the cluster finds results, it saves them in the same bucket.

You will need:

  • a file bucket (S3 or compatible) to store your hashes,
  • a Kubernetes cluster with as many machines as you like.

We use DigitalOcean as an example.

Create a bucket named tezos-proto-cruncher. For our example, we follow this DigitalOcean Spaces guide.

Then transfer the proto binary file to the bucket using the DigitalOcean Spaces web interface, or an utility such as s3cmd:

$ s3cmd put mumbai_v s3://tezos-proto-cruncher

Prepare a values file

Create a file called mumbai_v.yaml with the following content:

s3AccessKeyId: DO00Y...
s3SecretAccessKey: '/5CFZV...'
bucketEndpointUrl: 'ams3.digitaloceanspaces.com'
bucketRegion: 'ams'
bucketName: "tezos-proto-cruncher"
protoName: "mumbai_v"
vanityString: "PtMumbai"

Where:

  • s3*: the S3-compatible credentials
  • bucketEndpointUrl: the endpoint of your S3-compatible service (for DigitalOcean, see this tutorial)
  • bucketRegion: the region of the bucket (for example ams)
  • bucketName: name of your bucket (so the s3 url is s3://<name>)
  • protoName: the name of the file containing your proto
  • vanityString: the string you want your proto to start with

Create a cluster

Go to your cloud platform of choice and create a k8s cluster.

The proto-cruncher is configured as a kubernetes daemon set which means it runs on every virtual machine of your cluster.

So, you can pick the appropriate number of machines based on how fast you need the hashes.

Such a cluster will find a 6-character hash such as PtMumbai in a few hours. Don’t forget to switch it off afterwards!

In our example, we use a DigitalOcean k8s cluster. See quick start.

Install the chart

You need the kubectl and helm utilities. For more details, see tezos-k8s prerequisites.

helm repo add oxheadalpha https://oxheadalpha.github.io/tezos-helm-charts/
helm install -f /path/to/mumbai_v.yaml cruncher oxheadalpha/tezos-proto-cruncher --namespace cruncher --create-namespace

That’s it! All vCPUS of all the nodes of your cluster are now searching for a vanity hash.

Go to bed, the next morning you should see a few results in your bucket. If not, get bigger VMs.

The results consist of files named after the protocol hash. The content of the file is the vanity nonce. For example: (* Vanity nonce: 3300821025205842 *).

Submit your Proposal

Copy and paste the nonce into the source code main.ml file, replacing the original vanity hash. Make sure to not introduce any new space or newline.

Then check that the octez-protocol-compiler command gives you the expected hash:

$ ./octez-protocol-compiler -hash-only src/proto_016_*/lib_protocol
PtMumbaiveNjgvoAng9E3AtNqtBtCQWqpXJdPEdAanAYCZbCgey

Compile your protocol again.

It is always recommended to test your protocol thoroughly before injection. The Octez documentation explains how to. When unsure, do not hesitate to ask for help.

You are now ready to inject your proposal. To do so, you need access to your baker key and a public node.

Submit the command:

octez-client submit proposals for <YOUR_BAKER_ADDRESS> PtMumbaiveNjgvoAng9E3AtNqtBtCQWqpXJdPEdAanAYCZbCgey

Your proposal is now injected. Commit your changes and push them to a public repo, where other bakers and developers can examine them.

Wrap up

Uninstall your chart with the command:

helm uninstall cruncher --namespace cruncher

Then delete your cluster, if applicable.

--

--