Skip to main content

Hotkeys generation

Intermediate
Rosetta
Tutorial

This section will explain how to generate a hotkey for neuron management and add or remove hotkeys to your neuron using ICP Rosetta. The recommended way to get hotkeys is to programmatically generate them using the same process used in the public ic repository. However, it is possible to generate hotkeys manually as described below.

Generating a hot key

The manual hotkey generation process consists in generating a PEM file, then deriving the corresponding private and public keys.

Generate PEM

To generate the keys, start with generating a private PEM file:

openssl genpkey -algorithm ed25519 -outform PEM -out private.pem

Example output:

-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEIHAOt4HGrNdcIFhBy7N9p6iq3iRowd4NZjDZ8aaaDCcX
-----END PRIVATE KEY-----

Then create the public PEM from it:

openssl pkey -in private.pem -pubout > public.pem

Example output:

-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEA4JKtE2KNVUTo96cl202FgWv5ctwP7f1ds1O73PZ6+VE=
-----END PUBLIC KEY-----

Generating hex key representation

Create the private DER file:

openssl pkey -inform pem -outform der -in private.pem -out private.der

Create the public DER file:

openssl pkey -inform pem -outform der -in private.pem -out public.der -pubout

Hex representation

The generated DER files are in a binary format not intended to be readable by humans. But you can get a hex representation of both keys:

Private key

xxd -p private.der

Example output:

302e020100300506032b657004220420700eb781c6acd75c205841cbb37d
a7a8aade2468c1de0d6630d9f1a69a0c2717

Public key

xxd -p public.der

302a300506032b6570032100e092ad13628d5544e8f7a725db4d85816bf9
72dc0fedfd5db353bbdcf67af951

You need to keep only the last 32 bytes of the public key:

xxd -s 12 -c 32 -p public.der

Example output:

e092ad13628d5544e8f7a725db4d85816bf972dc0fedfd5db353bbdcf67af951

This is the public key you can use in Rosetta operations to identify your hotkey!


Frequently asked questions

  • Why do I get "Algorithm ed25519 not found" while generating the PEM file?

The version of OpenSSL included in macOS doesn't support ed25519 by default. You may have to install another version of OpenSSL (for example through brew), or run the command from a Linux machine.

Adding hotkeys to a neuron

Since version1.2.0
Idempotent?yes
Minimal access levelcontroller

The ADD_HOTKEY operation adds a hotkey to the neuron. The Governance canister allows some non-critical operations to be signed with a hotkey instead of the controller’s key (e.g., voting and querying maturity). The neuron you are trying to add a hotkey for must not have more than 10 hotkeys already linke to it.

The command has two forms: one form accepts an ICP principal as a hotkey, another form accepts a public key.

Add a principal as a hotkey

curl --location '0.0.0.0:8081/construction/payloads'  --header 'Content-Type: application/json' --data '
{
"network_identifier": {
"blockchain": "Internet Computer",
"network": "00000000000000020101"
},
"public_keys": [
{
"hex_bytes": "047a83e378053f87b49aeae53b3ed274c8b2ffbe59d9a51e3c4d850ca8ac1684f7131b778317c0db04de661c7d08321d60c0507868af41fe3150d21b3c6c757367",
"curve_type": "secp256k1"
}
],
"operations": [
{
"operation_identifier": {
"index": 0
},
"type": "ADD_HOTKEY",
"account": {
"address": "8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4"
},
"metadata": {
"neuron_index": 1,
"principal": "sp3em-jkiyw-tospm-2huim-jor4p-et4s7-ay35f-q7tnm-hi4k2-pyicb-xae"
}
}
],
"metadata": null
}'

Add a public key as a hotkey

curl --location '0.0.0.0:8081/construction/payloads'  --header 'Content-Type: application/json' --data
'{
"network_identifier": {
"blockchain": "Internet Computer",
"network": "00000000000000020101"
},
"public_keys": [
{
"hex_bytes": "047a83e378053f87b49aeae53b3ed274c8b2ffbe59d9a51e3c4d850ca8ac1684f7131b778317c0db04de661c7d08321d60c0507868af41fe3150d21b3c6c757367",
"curve_type": "secp256k1"
}
],
"operations": [
{
"operation_identifier": {
"index": 0
},
"type": "ADD_HOTKEY",
"account": {
"address": "8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4"
},
"metadata": {
"neuron_index": 1,
"public_key": {
"hex_bytes": "04995aca22a49c8e579a8501f38d64952054f4b33f793376f1d013d93edd10a55c29522e41b5fed16283b70a6f3fa00c6d66420938e89c5d67a58f30c8a5df059e",
"curve_type": "secp256k1"
}
}
}
],
"metadata": null
}'

When you call NeuronInfo afterwards you can see the hotkey added to the list of hotkeys, like so.

{
"transaction_identifier": {
"hash": "0000000000000000000000000000000000000000000000000000000000000000"
},
"metadata": {
"operations": [
{
"account": {
"address": "8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4"
},
"metadata": {
"controller": "iowfl-yzooa-br3dt-77erl-nlm7f-kplhq-php75-hw3an-aeqn2-swh4t-3qe",
"followees": {},
"hotkeys": [
"ykyib-l2eur-2idfx-uyka5-hag7i-3mypz-3kqc2-d6pid-tzat5-bysqw-mae"
],
"kyc_verified": true,
"maturity_e8s_equivalent": 0,
"neuron_fees_e8s": 0,
"neuron_id": 3094748712371737240,
"neuron_index": 0,
"staked_maturity_e8s": 0,
"state": "NOT_DISSOLVING"
},
"operation_identifier": {
"index": 0
},
"status": "COMPLETED",
"type": "NEURON_INFO"
}
]
}
}

Removing hotkeys from a neuron

The REMOVE_HOTKEY operation remove a previously added hotkey from the neuron. The command has two forms: one form accepts an ICP principal as a hotkey, another form accepts a public key.

Remove a principal as a hotkey

curl --location '0.0.0.0:8081/construction/payloads'  --header 'Content-Type: application/json' --data '
{
"operation_identifier": { "index": 0 },
"type": "REMOVE_HOTKEY",
"account": { "address": "907ff6c714a545110b42982b72aa39c5b7742d610e234a9d40bf8cf624e7a70d" },
"metadata": {
"neuron_index": 0,
"principal": "sp3em-jkiyw-tospm-2huim-jor4p-et4s7-ay35f-q7tnm-hi4k2-pyicb-xae"
}
}'

Remove a public key as a hotkey

curl --location '0.0.0.0:8081/construction/payloads'  --header 'Content-Type: application/json' --data
' {
"operation_identifier": { "index": 0 },
"type": "REMOVE_HOTKEY",
"account": { "address": "907ff6c714a545110b42982b72aa39c5b7742d610e234a9d40bf8cf624e7a70d" },
"metadata": {
"neuron_index": 0,
"public_key": {
"hex_bytes": "1b400d60aaf34eaf6dcbab9bba46001a23497886cf11066f7846933d30e5ad3f",
"curve_type": "edwards25519"
}
}
}'

After this operation the hotekey should not be included in the NeuronInfo anymore.