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:
Build the payment address used to pay for the transaction fees:
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.
cardano-cli governance create-poll \
--question "Best name for a dog?" \
--answer "Cheeto" \
--answer "Ham" \
--answer "Rocco" \
--nonce 1 \
--out-file poll.cbor > poll.json
Poll created successfully.
Please submit a transaction using the resulting metadata.
{
"94": {
"map": [
{
"k": {
"int": 0
},
"v": {
"list": [
{
"string": "Best name for a dog?"
}
]
}
},
{
"k": {
"int": 1
},
"v": {
"list": [
{
"list": [
{
"string": "Cheeto"
}
]
},
{
"list": [
{
"string": "Ham"
}
]
},
{
"list": [
{
"string": "Rocco"
}
]
}
]
}
}
]
}
}
Hint (1): Use '--json-metadata-detailed-schema' and '--metadata-json-file' from the build or build-raw commands.
Hint (2): You can redirect the standard output of this command to a JSON file to capture metadata.
Note that a serialized version of the poll suitable for sharing with participants has been generated at 'poll.cbor'.
cat poll.cbor
{
"type": "GovernancePoll",
"description": "An on-chain poll for SPOs: Best name for a dog?",
"cborHex": "a1185ea200817442657374206e616d6520666f72206120646f673f0183816643686565746f816348616d8165526f63636f"
}
cat poll.cbor
{
"type": "GovernancePoll",
"description": "An on-chain poll for SPOs: Best name for a dog?",
"cborHex": "a1185ea200817442657374206e616d6520666f72206120646f673f0183816643686565746f816348616d8165526f63636f"
}
Best name for a dog?
→ Cheeto
Poll answer created successfully.
Please submit a transaction using the resulting metadata.
To be valid, the transaction must also be signed using a valid key
identifying your stake pool (e.g. your cold key).
Hint (1): Use '--json-metadata-detailed-schema' and '--metadata-json-file' from the build or build-raw commands.
Hint (2): You can redirect the standard output of this command to a JSON file to capture metadata.
Best name for a dog?
[0] Cheeto
[1] Ham
[2] Rocco
Please indicate an answer (by index): 0
Poll answer created successfully.
Please submit a transaction using the resulting metadata.
To be valid, the transaction must also be signed using a valid key
identifying your stake pool (e.g. your cold key).
Hint (1): Use '--json-metadata-detailed-schema' and '--metadata-json-file' from the build or build-raw commands.
Hint (2): You can redirect the standard output of this command to a JSON file to capture metadata.