Voting on Governance Actions
Now that we have authorized our hot credential, we are able to vote on governance actions.
Step 1: Obtaining relevant voting information
The voting group is responsible for deliberating, documenting, and casting votes on governance action. When they request a vote transaction from you, they are responsible for providing:
The ID of the governance action for which to vote, consisting of a tx ID and governance action index.
A URL that resolves to a rationale document in CIP-100-compliant JSONLD format.
The decision for their vote (yes, no, or abstain).
If you have been following along with the guide, you can create a sample
governance action with the command create-dummy-gov-action
$ create-dummy-gov-action
Estimated transaction fee: Coin 174213
Transaction successfully submitted.
Governance Action Tx ID: 662d4c4eb59673a2c67882a58dd42465088973edc4f5314211169ea2c981dbe3
Governance Action Index: 0
This will print out the governance action’s tx ID and index, both of which will be needed later.
For the rationale document URL, we will use
https://raw.githubusercontent.com/cardano-foundation/CIPs/master/CIP-0100/example.json,
and we will be voting yes on the governance action.
The only missing piece of information we need to prepare is a hash of the
rationale document, for downstream verification of the contents. In accordance
with CIP-100, the way to obtain this hash is by using the hashing algorithm
specified in the metadata "hashAlgorithm": "blake2b-256". We can use the CLI
to help with this:
$ ANCHOR=https://raw.githubusercontent.com/cardano-foundation/CIPs/master/CIP-0100/example.json
$ cardano-cli hash anchor-data \
--text "$(curl -s $ANCHOR)" \
--out-file anchor.hash
As before, we also need the current output of the hot NFT script:
$ fetch-hot-nft-utxo
Alternatively, you can use a cardano-cli query for this:
$ cardano-cli conway query utxo --address $(cat init-hot/nft.addr) --output-json > hot-nft.utxo
Step 2: Creating the assets
Now we can use orchestrator-cli to build our transaction assets:
$ orchestrator-cli vote \
--utxo-file hot-nft.utxo \
--hot-credential-script-file init-hot/credential.plutus \
--governance-action-tx-id $(cardano-cli conway query gov-state | jq -r '.proposals[0].actionId.txId') \
--governance-action-index 0 \
--yes \
--metadata-url $ANCHOR \
--metadata-hash $(cat anchor.hash) \
--out-dir vote
Note
You can cast more than one vote per transaction. To specify multiple votes,
specify --governance-action-tx-id, --governance-action-index,
(--yes|--no|--abstain), --metadata-url, and --metadata-hash once
for each vote. Be careful about the ordering when specifying multiple votes,
as the order of the arguments determines how they are grouped when building
the vote file.
Let’s see what assets were created.
$ ls vote -1
datum.json
redeemer.json
value
vote
As before, the output datum is the same as the input datum:
diff <(jq 'to_entries | .[0].value.inlineDatum' < hot-nft.utxo) <(jq '.' < vote/datum.json)
And the redeemer instructs the script to perform the Vote action:
cat vote/redeemer.json
{
"constructor": 7,
"fields": []
}
Ignoring the value file, which as before is just a convenience for building
the transaction with cardano-cli, the last file of note is vote. This
is a vote file that we will add to the transaction to cast the vote:
$ cardano-cli conway governance vote view --vote-file vote/vote
{
"committee-scriptHash-b8928f246d726b59c51f33fc9d643b808dd273e5d9985762e464783d": {
"febe3bd850e2c34ec6612f32d6438c9ccf965ea3b1bcc843efe3c42331fd3fec#0": {
"anchor": {
"dataHash": "7b7d4a28a599bbb8c08b239be2645fa82d63a848320bf4760b07d86fcf1aabdc",
"url": "https://raw.githubusercontent.com/cardano-foundation/CIPs/master/CIP-0100/example.json"
},
"decision": "VoteYes"
}
}
}
Step 3: Create the Vote Transaction
Now we have everything we need to build the transaction.
$ tx-bundle build \
--tx-in "$(get-orchestrator-ada-only | jq -r '.key')" \
--tx-in-collateral "$(get-orchestrator-ada-only | jq -r '.key')" \
--tx-in $(jq -r 'keys[0]' hot-nft.utxo) \
--tx-in-script-file init-hot/nft.plutus \
--tx-in-inline-datum-present \
--tx-in-redeemer-file vote/redeemer.json \
--tx-out "$(cat vote/value)" \
--tx-out-inline-datum-file vote/datum.json \
--required-signer-group-name voting \
--required-signer-group-threshold 2 \
--required-signer-hash $(orchestrator-cli extract-pub-key-hash example-certificates/child-7.cert) \
--required-signer-hash $(orchestrator-cli extract-pub-key-hash example-certificates/child-8.cert) \
--required-signer-hash $(orchestrator-cli extract-pub-key-hash example-certificates/child-9.cert) \
--vote-file vote/vote \
--vote-script-file init-hot/credential.plutus \
--vote-redeemer-value {} \
--change-address $(cat orchestrator.addr) \
--out-file vote/body.txbundle
Estimated transaction fee: Coin 702241
Most of what we covered when building the hot credential authorization script also applies here, so we won’t cover it again. The only difference is that we are attaching and authorizing a vote file instead of a certificate, but the mechanism is similar.
Step 4. Distribute the Transaction to The Voting Group
We now have an unsigned transaction body which we need our voters to sign.
$ cc-sign -q \
--tx-bundle-file vote/body.txbundle \
--private-key-file example-certificates/children/child-8/child-8.private \
--out-file vote/child-8.witbundle
$ cc-sign -q \
--tx-bundle-file vote/body.txbundle \
--private-key-file example-certificates/children/child-9/child-9.private \
--out-file vote/child-9.witbundle
$ tx-bundle witness \
--all \
--tx-bundle-file vote/body.txbundle \
--signing-key-file orchestrator.skey \
--out-file vote/orchestrator.witbundle
Step 5. Assemble and Submit the Transaction
Finally, we can put everything together to submit the transaction:
$ tx-bundle assemble \
--tx-bundle-file vote/body.txbundle \
--witness-bundle-file vote/child-8.witbundle \
--witness-bundle-file vote/child-9.witbundle \
--witness-bundle-file vote/orchestrator.witbundle \
--out-file vote/tx.json
$ cardano-cli conway transaction submit --tx-file vote/tx.json
Transaction successfully submitted.
Step 6. Verify the Vote On Chain
We can see the results of our vote by querying the gov state from the node:
$ cardano-cli conway query gov-state | jq '.proposals[]'
{
"actionId": {
"govActionIx": 0,
"txId": "febe3bd850e2c34ec6612f32d6438c9ccf965ea3b1bcc843efe3c42331fd3fec"
},
"committeeVotes": {
"scriptHash-b8928f246d726b59c51f33fc9d643b808dd273e5d9985762e464783d": "VoteYes"
},
"dRepVotes": {},
"expiresAfter": 121,
"proposalProcedure": {
"anchor": {
"dataHash": "0000000000000000000000000000000000000000000000000000000000000000",
"url": "https://example.com"
},
"deposit": 1000000000,
"govAction": {
"tag": "InfoAction"
},
"returnAddr": {
"credential": {
"keyHash": "9f2512df96406ee5033478c432c7f10622ebf4a3715c0a8d50096238"
},
"network": "Testnet"
}
},
"proposedIn": 21,
"stakePoolVotes": {}
}