Submitting Your Vote as Validator

Once you have either 100k PI ready to stake for an individual node, or have registered as a Validator Candidate and 100k PI delegated, you are ready to submit your vote as a validator.

You can submit your vote in the second phase of each Epoch, from 75% to 85% of the Epoch.


Block Number

What you can do

0% ~ 75%

start_block ~ vote_start_block - 1

apply candidates and delegate

75% ~ 85%

vote_start_block ~ vote_end_block


85% ~ 95%

reveal_start_block ~ reveal_end_block

reveal vote

95% ~ 100%

reveal_end_block + 1 ~ end_block

check next epoch’s info

There are three phases to submitting your vote. Getting your variables, generating the vote hash, then sending the vote hash as a transaction.

Preparing Your Variables

In order to submit your Vote, you will need your address, BLS public key, and the amount you are staking (by yourself or with delegations) with your node.

BLS Public Key

Suppose you have a BLS key file, priv_validator.json, that looks like this:

"address": "4CACBCBF218679DCC9574A90A2061BCA4A8D8B6C",
"consensus_priv_key": [
"consensus_pub_key": [

The consensus_pub_key is what you will need. From the example above:


Staking Value

You will also need the amount you are staking. This part is a bit more tricky as we need to convert your balance or total balance (balance + delegated balance) into p-wei and then convert it from decimal to hex. There are many ways to do this, but for this guide, we will try to simplify it.

For this purpose, we will use the RPC to query for your full balance. To do this, we will use:


Returns the overall balance of the account of a given address.


  1. from: address, 20 Bytes - address to check for balance.

  2. blockNumber: QUANTITY|TAG - integer block number, or the string "latest", "earliest" or "pending"

  3. fullDetail: Boolean - If true it returns the full detail of proxied/reward object under this address

params: [


  1. balance: QUANTITY - integer of the current balance in p-wei.

  2. total_delegateBalance: QUANTITY - total delegate balance in p-wei to other address

  3. total_depositBalance: QUANTITY - deposit balance in p-wei for Validator Stake

  4. total_depositProxiedBalance: QUANTITY - total deposit proxied balance in p-wei for Validator Stake

  5. total_pendingRefundBalance: QUANTITY - total pending refund balance in p-wei which will be return to delegate at the end of Current Epoch

  6. total_proxiedBalance: QUANTITY - total proxied balance in p-wei delegate from other address

  7. total_rewardBalance: QUANTITY - total pending reward balance in p-wei of this address

  8. proxied_detail: Object - detail record of each address's proxied data, including proxied balance, deposit proxied balance and pending refund balance

  9. reward_detail: Object - detail record of this address's reward data, including how much balance in p-wei will be given at the end of each epoch


curl -X POST -H "Content-Type:application/json" --data '{"jsonrpc":"2.0","method":"eth_getFullBalance","params":["your_address", "latest", true],"id":1}' localhost:6969/pchain | jq '.'

Where your_address is the node address that you are registering. You will also notice that at the end of the call, the curl response is piped " | " into jq which makes the output much more readable.

This will output something like the below:

  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "balance": "0x16b008e27eb56263",
    "proxied_detail": {
      "0x00000017f6f17ce18faa53d7010fa66acd0e1fb9": {
        "ProxiedBalance": "0x0",
        "DepositProxiedBalance": "0x25a84ac2edaef1a00000",
        "PendingRefundBalance": "0x0"
      "0x04be9e1c25ecb8106afe975e7854b6e2ad603d98": {
        "ProxiedBalance": "0x0",
        "DepositProxiedBalance": "0x1a16af753a6cbd00000",
        "PendingRefundBalance": "0x0"
      "0x0650f28ac7c2ac224c40f3d831d54d1b4b2cf3d6": {
        "ProxiedBalance": "0x0",
        "DepositProxiedBalance": "0x6c6b935b8bbd400000",
        "PendingRefundBalance": "0x0"
      "0x0b7556d0955f00a4bc3d9762f303edcdfa1e18c5": {
        "ProxiedBalance": "0x0",
        "DepositProxiedBalance": "0x164288e57717cf8b1800",
        "PendingRefundBalance": "0x0"
      "0xff764950026852057701674f1b0341b50dc38e96": {
        "ProxiedBalance": "0x0",
        "DepositProxiedBalance": "0x566f1e2b2d4726b0000",
        "PendingRefundBalance": "0x0"
    "total_delegateBalance": "0x25a84ac2edaef1a00000",
    "total_depositBalance": "0x0",
    "total_depositProxiedBalance": "0x9744d24923260b7d1a800",
    "total_pendingRefundBalance": "0x2ca43ff57b8edf380000",
    "total_proxiedBalance": "0x0",
    "total_rewardBalance": "0x27032171401213718ee4"

If you are a self staked node without delegations, the value you will use for your vote is the total_delegateBalance, which is just the balance within the wallet:

"total_delegateBalance": "0x25a84ac2edaef1a00000"

If you are a Candidate node with delegations, the value you will use for your vote is the total_depositProxiedBalance, which is the balance within the wallet + the sum of the delegations:

"total_depositProxiedBalance": "0x9744d24923260b7d1a800"

If you convert these values from hex to decimal, you will find that it agrees with the numbers in PIScan, multiplied by 1000000000000000000. For more on FullBalance, see here.

Generating Vote Hash

To generate the vote hash, you will use the Javascript Console. Navigate into the pchain directory.

cd ~/pchain

And attach to the console:

./bin/pchain attach .pchain/pchain/pchain.ipc

Once you are in the console, we will set all the variables for the getVoteHash function:

var address = "4CACBCBF218679DCC9574A90A2061BCA4A8D8B6C";
var blspubkey = "085586D41F70435700850E19B7DE54B3E793C5EC4C6EC502D19030EF4F2122823E5A765E56CBA7B4C57E50561F77B022313C39895CA303F3C95D7B7282412F334778B95ACE046A79AEA4DB148334527250C8895AC5DB80459BF5D367236B59AF2DB5C0254E30A6D8CD1FA10AB8A5D872F5EBD312D3160D3E4DD496973BDC75E0";
var amount = "0x9744d24923260b7d1a800";
var salt = "ilovepchain"; //this string can be whatever you like

Where each value is the value associated with your node address (without 0x prefix), BLS public key, and amount from above. The salt is just a random string that is used to make the output hash safe from others being able to determine the votes and those that submitted them. Each one will return undefined.

Please note each of these values will be needed when you reveal your vote in order for it to be a successful vote.

Running the web3.getVoteHash() function with those variables as input will generate the vote hash.


Take note of this as it will be needed in the next step. You can then exit the console with exit.

Sending Vote Hash Transaction

Now that you have your vote hash, you are ready to send it with the RPC, with the tdm_voteNextEpoch function:

curl -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0","method":"tdm_voteNextEpoch","params":["address", "vote_hash"],"id":1}' localhost:6969/pchain

Where address is the node address you are registering and vote_hash is the hash you just generated. Using the example above:

curl -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0","method":"tdm_voteNextEpoch","params":["0x4CACBCBF218679DCC9574A90A2061BCA4A8D8B6C", "0x4dcb9f6e059051c58cc06ee0c038af4bffc18e85983540a72012bce56d2c37ec"],"id":1}' localhost:6969/pchain

If successful, this will return a transaction hash that can be checked in PIScan for success.

The next step will be to reveal the vote at the 85% - 95% period of the epoch.

Last updated