ICP staking with seed phrase and air-gapped computer
Requirements
You can only stake with seed phrase and air-gapped computer if you are already doing ICP custody with seed phrase and air-gapped machine. This page assumes you are successfully doing self-custody of ICP as described in that article.
This section assumes you successfully installed the QR tools on your air-gapped computer from ICP custody with seed phrase and air-gapped machine.
In this section, we need to “bridge the air gap.” This means that we will continue to perform the sensitive operations within the air-gapped computer, but we will use a networked smartphone’s QR code scanner to send the messages from the air-gapped computer to the Internet Computer.
Terminology
To “stake ICP” and to “create a neuron” are the same activity so they are used interchangeably.
How to stake a neuron
Summary of steps
- Send ICP to your ledger account identifier
- Create a neuron
- Set dissolve delay of neuron
Step 1: Send ICP to your ledger account identifier
This account identifier lives in the Ledger canister that maintains the ICP addresses for the entire network. This account identifier is analogous to “addresses” in other blockchains. You need to send the ICP you want to stake to the ledger account identifier. In the example case, the ledger account 77b5eb9a465f4ce6f4da494ee2bfedeefe0b52d106e0272556c1ad991f99e3da
so that is the address we will use.
To create a neuron, you need to stake a minimum of 1 ICP. Anything less will not create a neuron.
If you cannot send ICP to your ledger account identifier, do not continue. Try again, check out support, or submit a question to support.
Step 2: Create a neuron
Step 2a: Generate a signed message to “create a neuron” using quill
On the air-gapped computer:
/ This is just the structure, copy/pasting WILL NOT work. See below for working example of a command $ target/release/quill --pem-file private.pem neuron-stake --name $NAME --amount $AMOUNT
For this command, the $NAME is an arbitrary string, up to 8 characters, that you can use to identify your neuron for the purposes of topping up later with quill. For example, if you intend to have only one eight-year neuron, you could use the name 8yneuron. This string has no meaning otherwise, and will not be visible anywhere else. You can store the string on your air-gapped computer. It can in theory be recovered if lost but there is currently no tooling for recovery, so we recommend you also write the string down.
The $AMOUNT should not include the transaction fee, but remember that it will still be deducted from your account, so if you wish to stake everything you’ve got, stake your balance minus the 0.0001 ICP fee.
Here is the same command with the fields $NAME (“neuron3”) and $AMOUNT (1.01) filled out, but you should choose your own fields.
On the air-gapped computer:
// Create the message that tells IC "create the neuron" and save it in "message.json" $ target/release/quill --pem-file private.pem neuron-stake --name neuron3 --amount 1.01 > message.json
Step 2b: Bridge the air gap: Send the "create neuron" message to the Internet Computer using a QR code
Since your air-gapped computer is not connected to the internet, we will use a QR app to send the message generated above to the Internet Computer. We will use IC Transaction Scanner which lives in a canister (and whose code is visible here: https://github.com/ninegua/ic-qr-scanner).
See Bridging the air gap with quill and QR codes
On your air-gapped computer terminal, press ENTER to get the next QR code to scan, repeat scanning and sending messages until there are no more.
When you do this, the browser on your smartphone will get a response with the id of the new neuron created.
After sending the message from IC Transaction scanner, do not close your browser window. Wait to get a response on IC Transaction Scanner that confirms the neuron was successfully created. A neuron id will come back to you as a response on the browser that looks like this:
( record { result = opt variant { NeuronId = record { id = 5_241_875_388_871_980_017 } }; }, )
In the example above, the neuron id is 5241875388871980017
.
You can view your neuron on community dashboards like ic.rocks by going to URL: https://ic.rocks/neuron/
For example, neuron 5241875388871980017
, https://ic.rocks/neuron/5241875388871980017
Step 3: Set dissolve delay of neuron
Now that you have a neuron, this section adds a dissolve delay to that neuron. Your ICP is not staked until the neuron has a dissolve delay.
Step 3a: Create a message to the neuron to add dissolve delay
To increase the dissolve delay of a neuron whose id is $NEURON_ID, we will use a command of the form:
// This is just the structure, copy/pasting WILL NOT work. See below for working command $ target/release/quill --pem-file private.pem neuron-manage $NEURON_ID --additional-dissolve-delay-seconds $SECONDS
This shows the neuron-manage subcommand, which is used to manipulate neurons after they have been staked. In this case, we are adding $SECONDS seconds to the delay time.
The following table gives typical values for $SECONDS:
Length | number |
---|---|
Six months | 15778800 (60 seconds * 60 minutes * 24 hours * 182.625 days) |
One year | 31557600 (60 seconds * 60 minutes * 24 hours * 365.25 days) |
Four years | 126230400 (60 seconds * 60 minutes * 24 hours * 365.25 days * 4 years) |
Eight years | 252460800 (60 seconds * 60 minutes * 24 hours * 365.25 days * 8 years) |
If you specify a dissolve delay longer than 8 years, it will be rounded down to 8 years.
In our example, we will start a 1-year dissolve, so we will use quill to craft the following command:
On the air-gapped computer:
// Add the dissolve delay $ target/release/quill --pem-file private.pem neuron-manage 5241875388871980017 --additional-dissolve-delay-seconds 31557600 > message.json // Using the bash script, create a QR code from the "message.json" file created by quill with your message $ bash ./quill-qr.sh < message.json
Step 3b: Send the message to the IC by bridging the air gap
Since your air-gapped computer is not connected to the internet, we will use a QR app to send the message generated above to the Internet Computer. We will use IC Transaction Scanner which lives in a canister (and whose code is visible here: https://github.com/ninegua/ic-qr-scanner).
How to add more ICP to the neuron (“top up the neuron”)
Step 1: Create a message to the neuron to "top up the neuron"
Structure of command:
$ target/release/quill --pem-file private.pem neuron-manage $NEURON_ID --disburse
Command with example variables:
//Craft message to send 42 ICP to the neuron named "neuron3". Store in "message.json" $ target/release/quill --pem-file private.pem neuron-stake --name neuron3 --amount 42.20 > message.json // Using the bash script, create a QR code from the "message.json" file created by quill with your message $ bash ./quill-qr.sh < message.json
Step 2: Send the message to the IC via QR code
Since your air-gapped computer is not connected to the internet, we will use a QR app to send the message generated above to the Internet Computer. We will use IC Transaction Scanner which lives in a canister (and whose code is visible here: https://github.com/ninegua/ic-qr-scanner).
How to add a hot key to the neuron
A hot key is a lot like a read-only view of a neuron, in that it lets you use a different controller to see the balance, maturity, dissolve delay and other details of a neuron. Where this becomes most useful is in conjunction with the NNS frontend dapp and your Internet Identity.
Step 1: Log into the NNS Frontend dapp
(note: This will require you create an Internet Identity)
Log in to the NNS frontend dapp and visit the Neurons tab, it will display a principal id.
Step 2: Get the principal id from your NNS Frontend dapp
In our example variable it is 2xt3l-tqk2i-fpygm-lseru-pvgek-t67vb-tu3ap-k0mnu-dr4hl-z3kpn-o2e"
.
Step 3: Create a message to the neuron to "add hot key to the neuron"
Structure of command:
$ target/release/quill --pem-file private.pem neuron-manage $NEURON_ID --add-hot-key "$PRINCIPAL"
Command with example variables:
// Add the hot key from the NNS frontend dapp to your self-custodied neuron $ target/release/quill --pem-file private.pem neuron-manage 5241875388871980017 --add-hot-key "2xt3l-tqk2i-fpygm-lseru-pvgek-t67vb-tu3ap-k0mnu-dr4hl-z3kpn-o2e" > message.json // Using the bash script, create a QR code from the "message.json" file created by quill with your message $ bash ./quill-qr.sh < message.json
Step 4: Send the message to the IC via QR code
Since your air-gapped computer is not connected to the internet, we will use a QR app to send the message generated above to the Internet Computer. We will use IC Transaction Scanner which lives in a canister (and whose code is visible here: https://github.com/ninegua/ic-qr-scanner).
How to vote with a neuron
The easiest way to vote with a neuron that is self-custodied is to add the NNS Frontend dapp as a hot key.
If you add the NNS Frontend dapp as a hot key, it cannot spawwn, disburse, start dissolve, stop dissolve your neuron, but it can vote on its behalf.
How to set your neuron to follow another neuron
The easiest way to vote with a neuron that is self-custodied is to add the NNS Frontend dapp as a hot key.
If you add the NNS Frontend dapp as a hot key, it cannot spawwn, disburse, start dissolve, stop dissolve your neuron, but it can set a follow relationship with another neuron.
How to collect a neuron’s voting rewards
Step 1: Create a message to the neuron to "spawn a neuron"
Structure of command:
$ target/release/quill --pem-file private.pem neuron-manage $NEURON_ID --spawn > message.json
Command with example variables:
Assume 5241875388871980017
is the neuron ID of the neuron creating rewards.
$ target/release/quill --pem-file private.pem neuron-manage 5241875388871980017 --spawn > message.json // Using the bash script, create a QR code from the "message.json" file created by quill with your message $ bash ./quill-qr.sh < message.json
Step 2: Send the message to the IC via QR code
Since your air-gapped computer is not connected to the internet, we will use a QR app to send the message generated above to the Internet Computer. We will use IC Transaction Scanner which lives in a canister (and whose code is visible here: https://github.com/ninegua/ic-qr-scanner).
This will return a new neuron ID. Record it.
Step 3: Start dissolving the newly-spawned neuron
Follow instructions on ICP staking with seed phrase and air-gapped computer#How to start the dissolve process of a neuron with the neuron ID of the newly-spawned neuron.
Step 4: Disburse the newly-spawned neuron
Follow instructions on ICP staking with seed phrase and air-gapped computer#How_to_disburse_ICP_from_a_neuron "How to disburse ICP from a neuron" with the neuron ID of the newly-spawned neuron.
How to start the dissolve process of a neuron
Step 1: Create a message to the neuron to "start the dissolve process"
Structure of command:
$ target/release/quill --pem-file private.pem neuron-manage $NEURON_ID --start-dissolving
Command with example variables:
$ target/release/quill --pem-file private.pem neuron-manage 5241875388871980017 --start-dissolving > message.json // Using the bash script, create a QR code from the "message.json" file created by quill with your message $ bash ./quill-qr.sh < message.json
Step 2: Send the message to the IC via QR code
Since your air-gapped computer is not connected to the internet, we will use a QR app to send the message generated above to the Internet Computer. We will use IC Transaction Scanner which lives in a canister (and whose code is visible here: https://github.com/ninegua/ic-qr-scanner).
How to stop the dissolve process of a neuron
Step 1: Create a message to the neuron to "stop the dissolve process"
Structure of command:
$ target/release/quill --pem-file private.pem neuron-manage $NEURON_ID --stop-dissolving
Command with example variables:
$ target/release/quill --pem-file private.pem neuron-manage 5241875388871980017 --stop-dissolving > message.json // Using the bash script, create a QR code from the "message.json" file created by quill with your message $ bash ./quill-qr.sh < message.json
Step 2: Send the message to the IC via QR code
Since your air-gapped computer is not connected to the internet, we will use a QR app to send the message generated above to the Internet Computer. We will use IC Transaction Scanner which lives in a canister (and whose code is visible here: https://github.com/ninegua/ic-qr-scanner).
How to disburse ICP from a neuron
You can disburse the ICP from a neuron if any of the following are true:
a. Neuron was created without a dissolve delay
b. Neuron was created with dissolve delay, but it has dissolved longer than the dissolve delay.
Step 1: Create a message to the neuron to "disburse the ICP"
Structure of command:
$ target/release/quill --pem-file private.pem neuron-manage $NEURON_ID --disburse Command with example variables: On the '''air-gapped computer''': $ target/release/quill --pem-file private.pem neuron-manage 5241875388871980017 --disburse > message.json
// Using the bash script, create a QR code from the "message.json" file created by quill with your message $ bash ./quill-qr.sh < message.json Note: this command typically requires only one QR code being sent.
Step 2: Send the message to the IC via QR code
Since your air-gapped computer is not connected to the internet, we will use a QR app to send the message generated above to the Internet Computer. We will use IC Transaction Scanner which lives in a canister (and whose code is visible here: https://github.com/ninegua/ic-qr-scanner).
How to recreate a private key
If you lose your private key you can recreate it so long as you still have your seed phrase.
Step 1: place your seed phrase on your air-gapped computer
Retrieve your seed phrase from where you previously stored it and store it on your air-gapped computer in a file called seed.txt
.
In theory, you only need the first four characters of every word in your seed phrases since the remaining characters are ignored by the underlying key generation algorithm. That is why storage solutions like the Billfodl only store first four characters of every word.
To give a concrete example, suppose your seed phrase from keysmith was originally wage roast present easy mobile olympic panda double ready unveil knock stage
. When you store it in a Billfodl, you will actually only store the first four characters of each word like this: wage roas pres easy mobi olym pand doub read unve knoc stag
.
In short, in theory,
wage roast present easy mobile olympic panda double ready unveil knock stage
and
wage roas pres easy mobi olym pand doub read unve knoc stag
will generate the exact same private key
.
However, keysmith does not quite know that you only need the first four letters in each word (at the time of this writing), so when using keysmith to recreate your private key you need to recreate the original wage roast present easy mobile olympic panda double ready unveil knock stage
from the stored wage roas pres easy mobi olym pand doub read unve knoc stag
. You can do that by using using this list of BIP-39 words.
Step 2: Execute commands
Now that you have a seed.txt with the original seed phrase
, you can run this command in the directory where seed.txt
exists.
$ keysmith private-key -o private.pem
You will now have a file titled private.pem
with your private key
.
Step 3: Secure your seed phrase
properly
Now that you have generated your private key, you can leave it on your air-gapped computer. Make sure your seed phrase is properly stored for the future.
To properly store your seed phrase see where to store your seed phrase.
Step 4: Remove your seed phrase from your air-gapped computer
Now that the seed phrase
is properly stored. You should delete it from your computer before moving forward so no one can use it to recreate your private key
.
Remove it with the following command:
On the air-gapped computer:
$ rm -vf seed.txt