Polls

Cardano node v.8.0.0 introduced a new subset of commands to conduct polls among stake pool operators. A poll is official when it is signed by a genesis delegate key.

Working with the polling feature on a local cluster

See this tutorial on how to run a local cluster using mkfiles.sh script provided in the cardano-node repository.

The examples below were created on a local cluster generated with the mkfiles.sh script. You should be able to replicate the examples on your own cluster.

For this, you need to produce the following after running your cluster:

  1. Build the payment address used to pay for the transaction fees:

cardano-cli address build \
--payment-verification-key-file example/utxo-keys/utxo1.vkey \
--out-file example/utxo-keys/utxo1.addr \
--testnet-magic 42
  1. Get the hash of delegate 1 verification key:

cardano-cli genesis key-hash \
--verification-key-file example/delegate-keys/delegate1.vkey > example/delegate-keys/delegate1.hash
  1. Get the pool ID of pool 1:

cardano-cli stake-pool id \
--cold-verification-key-file example/pools/cold1.vkey \
--output-format hex > example/pools/pool.hex.id

Creating a poll

To create a poll, run:

Note that --nonce is an optional but recommended option. It accepts a UINT, which serves as a unique identifier, allowing the same question to be asked at different times.

Let's take a look at the serialized version of the poll:

Participants (SPOs) will use the poll.cbor file to create and submit their responses.

The delegate-key-holder proposing the poll will publish the poll in a transaction. To build such a transaction, run:

When building the transaction, you can use --required-signer-hash or

--required-signer

The example used --required-signer-hash because in a real-world scenario, the delegate signing keys are on cold storage and the build command requires access to a live node.

To get the hash of a delegate key, run:

Sign the transaction with the delegate signing key and with a payment signing key to pay for the transaction fees:

Note that in the example, the payment key is named utxo1.skey. This is the name given by the mkfiles.sh script. It is equivalent to a payment.skey that you might be familiar with.

When inspecting the transaction (question.tx.signed):

you should see something like this:

Note that the required signers field includes the hash of the delegate key, and the witnesses field includes the delegate and payment key data.

Finally, submit the transaction as usual:

You can use db-sync to check how it was registered online:

Of course, the hash matches the hash of the delegate key. This way, when SPOs see a poll signed with any of the delegate keys (verified by the delegate key hashes) they know this is an official poll.

Answering the poll

You can use the answer-poll command to create a response. Use the --answer option to immediately record your response by providing the index of your response. Alternatively, omit it to access the interactive method.

Note that in any case, you are redirecting the output to poll-answer.json.

The proponents of the poll will have distributed the poll.cbor file from above. As an SPO, you will need it to answer the poll. It will look like this:

Using --answer

This example votes for the option with index [0], Cheeto:

Responding interactively

Submitting the response in a transaction

When inspecting the signed transaction, required signers should contain the cold key hash (the pool ID), and witnesses should contain both the cold and payment key data:

You can use db-sync again to track responses:

Verifying answers

Finally, it’s possible to verify answers seen on-chain using the governance verify-poll command. ‘Verify’ means:

  • It checks that an answer is valid within the context of a given survey

  • It returns the list of signatories key hashes found in the transaction; in the case of a valid submission, one key hash will correspond to a known stake pool ID.

Using db-sync on your test

Note that the configuration.yaml file, produced by the mkfiles.sh script, does not contain the hashes of the genesis files, but db-sync demands them. Therefore, if you want to use db-sync, you will need to manually add the hashes of Byron, Shelley and Alonzo genesis files to the example/configuration.yamlfile:

Then, add the hashes to the configuration file (by default it only contains the paths):

Finally, when starting db-sync, you might see complaints about StartTime mismatch. If this happens, please make sure to replace the StartTime on Shelley Genesis with the value from StartTime on Byron Genesis. You should be good to go.

Last updated

Was this helpful?