2019-11-26 23:56:11 -05:00
|
|
|
# Paper Wallet Usage
|
|
|
|
|
2019-12-05 21:12:41 -05:00
|
|
|
Solana commands can be run without ever saving a keypair to disk on a machine.
|
|
|
|
If avoiding writing a private key to disk is a security concern of yours, you've
|
|
|
|
come to the right place.
|
2019-11-26 23:56:11 -05:00
|
|
|
|
|
|
|
{% hint style="warning" %}
|
2019-12-05 21:12:41 -05:00
|
|
|
Even using this secure input method, it's still possible that a private key gets
|
|
|
|
written to disk by unencrypted memory swaps. It is the user's responsibility to
|
|
|
|
protect against this scenario.
|
2019-11-26 23:56:11 -05:00
|
|
|
{% endhint %}
|
|
|
|
|
2019-12-19 20:59:07 -05:00
|
|
|
## Creating a Paper Wallet
|
|
|
|
|
|
|
|
Using the `solana-keygen` tool, it is possible to generate new seed phrases as
|
|
|
|
well as derive a keypair from an existing seed phrase and (optional) passphrase.
|
|
|
|
The seed phrase and passphrase can be used together as a paper wallet. As long
|
|
|
|
as you keep your seed phrase and passphrase stored safely, you can use them to
|
|
|
|
access your account.
|
|
|
|
|
|
|
|
{% hint style="info" %}
|
|
|
|
For more information about how seed phrases work, review this
|
|
|
|
[Bitcoin Wiki page](https://en.bitcoin.it/wiki/Seed_phrase).
|
|
|
|
{% endhint %}
|
|
|
|
|
|
|
|
### Seed Phrase Generation
|
|
|
|
|
|
|
|
Generating a new keypair can be done using the `solana-keygen new` command. The
|
|
|
|
command will generate a random seed phrase, ask you to enter an optional
|
|
|
|
passphrase, and then will display the derived public key and the generated seed
|
|
|
|
phrase for your paper wallet.
|
|
|
|
|
2020-01-30 17:20:04 -07:00
|
|
|
After copying down your seed phrase, you can use the
|
|
|
|
[public key derivation](#public-key-derivation) instructions to verify that you
|
|
|
|
have not made any errors.
|
|
|
|
|
2019-12-19 20:59:07 -05:00
|
|
|
```bash
|
|
|
|
solana-keygen new --no-outfile
|
|
|
|
```
|
|
|
|
|
|
|
|
{% hint style="warning" %}
|
|
|
|
If the `--no-outfile` flag is **omitted**, the default behavior is to write the
|
|
|
|
keypair to `~/.config/solana/id.json`
|
|
|
|
{% endhint %}
|
|
|
|
|
|
|
|
{% hint style="info" %}
|
|
|
|
For added security, increase the seed phrase word count using the `--word-count`
|
|
|
|
argument
|
|
|
|
{% endhint %}
|
|
|
|
|
|
|
|
For full usage details run:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
solana-keygen new --help
|
|
|
|
```
|
|
|
|
|
|
|
|
### Public Key Derivation
|
|
|
|
|
|
|
|
Public keys can be derived from a seed phrase and a passphrase if you choose to
|
|
|
|
use one. This is useful for using an offline-generated seed phrase to
|
|
|
|
derive a valid public key. The `solana-keygen pubkey` command will walk you
|
|
|
|
through entering your seed phrase and a passphrase if you chose to use one.
|
|
|
|
|
|
|
|
```bash
|
|
|
|
solana-keygen pubkey ASK
|
|
|
|
```
|
|
|
|
|
|
|
|
{% hint style="info" %}
|
|
|
|
Note that you could potentially use different passphrases for the same seed
|
|
|
|
phrase. Each unique passphrase will yield a different keypair.
|
|
|
|
{% endhint %}
|
|
|
|
|
|
|
|
The `solana-keygen` tool uses the same BIP39 standard English word list as it
|
|
|
|
does to generate seed phrases. If your seed phrase was generated with another
|
|
|
|
tool that uses a different word list, you can still use `solana-keygen`, but
|
|
|
|
will need to pass the `--skip-seed-phrase-validation` argument and forego this
|
|
|
|
validation.
|
|
|
|
|
|
|
|
```bash
|
|
|
|
solana-keygen pubkey ASK --skip-seed-phrase-validation
|
|
|
|
```
|
|
|
|
|
|
|
|
{% hint style="info" %}
|
|
|
|
Copy the derived public key to a USB stick for easy usage on networked computers
|
|
|
|
{% endhint %}
|
|
|
|
|
|
|
|
{% hint style="info" %}
|
|
|
|
A common next step is to [check the balance](#checking-account-balance) of the
|
|
|
|
account associated with a public key
|
|
|
|
{% endhint %}
|
|
|
|
|
|
|
|
For full usage details run:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
solana-keygen pubkey --help
|
|
|
|
```
|
2020-02-20 14:19:35 -07:00
|
|
|
|
|
|
|
## Verifying the Keypair
|
|
|
|
|
|
|
|
A keypair can be verified by following a variation on the
|
|
|
|
[offline signing](../offline-signing/README.md) procedure with a dummy transaction.
|
|
|
|
|
|
|
|
### Create and Sign a Dummy Transaction
|
|
|
|
|
|
|
|
Use offline signing to acquire the signature of a dummy transaction that can
|
|
|
|
be verified in the next step. A 0 Lamport [transfer](../cli/usage.md#solana-transfer)
|
|
|
|
is used to prevent inadvertent loss of funds. Additionally, an improbable _blockhash_
|
|
|
|
value is specified, as well as using the address of the _system program_ for the `TO`
|
|
|
|
argument, to ensure the transaction would be rejected by the _cluster_ should
|
|
|
|
it be submitted in error.
|
|
|
|
|
|
|
|
Command
|
|
|
|
|
|
|
|
```text
|
|
|
|
solana transfer 11111111111111111111111111111111 0 --sign-only \
|
|
|
|
--ask-seed-phrase keypair --blockhash 11111111111111111111111111111111
|
|
|
|
```
|
|
|
|
|
|
|
|
Prompt for seed phrase
|
|
|
|
|
|
|
|
```text
|
|
|
|
[keypair] seed phrase:
|
|
|
|
[keypair] If this seed phrase has an associated passphrase, enter it now. Otherwise, press ENTER to continue:
|
|
|
|
Recovered pubkey `AjTz9EX6vXB6EboKpFm7SwrbDannb6icjvEE632D3rfi`. Continue? (y/n): y
|
|
|
|
```
|
|
|
|
|
|
|
|
Output
|
|
|
|
|
|
|
|
```text
|
|
|
|
Blockhash: 11111111111111111111111111111111
|
|
|
|
Signers (Pubkey=Signature):
|
|
|
|
AjTz9EX6vXB6EboKpFm7SwrbDannb6icjvEE632D3rfi=3uZndChSmPoYfaCihC993E7EAHKDsuu53Ge6Dk1K6ULwhJkgcgiHNm9J1Geqq2azW6PKxQTFjC8rMm5bGxRcYWA
|
|
|
|
|
|
|
|
{"blockhash":"11111111111111111111111111111111","signers":["AjTz9EX6vXB6EboKpFm7SwrbDannb6icjvEE632D3rfi=3uZndChSmPoYfaCihC993E7EAHKDsuu53Ge6Dk1K6ULwhJkgcgiHNm9J1Geqq2azW6PKxQTFjC8rMm5bGxRcYWA"]}
|
|
|
|
```
|
|
|
|
|
|
|
|
### Verify the Signature
|
|
|
|
|
|
|
|
Using the _Signers_ output from the [previous step](#create-and-sign-a-dummy-transaction)
|
|
|
|
to reconstruct the transaction, this time specifying the _pubkey_ and _signature_
|
|
|
|
as in the submission step of [offline signing](../offline-signing/README.md). That is, the `--from` and
|
|
|
|
`--fee-payer` are explicitly set to the _pubkey_ rather than being taken from
|
|
|
|
the keypair (which is not queried this time).
|
|
|
|
|
|
|
|
Command
|
|
|
|
|
|
|
|
```text
|
|
|
|
solana transfer 11111111111111111111111111111111 0 --sign-only --from AjTz9EX6vXB6EboKpFm7SwrbDannb6icjvEE632D3rfi \
|
|
|
|
--signer AjTz9EX6vXB6EboKpFm7SwrbDannb6icjvEE632D3rfi=3uZndChSmPoYfaCihC993E7EAHKDsuu53Ge6Dk1K6ULwhJkgcgiHNm9J1Geqq2azW6PKxQTFjC8rMm5bGxRcYWA \
|
|
|
|
--blockhash 11111111111111111111111111111111 --fee-payer AjTz9EX6vXB6EboKpFm7SwrbDannb6icjvEE632D3rfi
|
|
|
|
```
|
|
|
|
|
|
|
|
Output
|
|
|
|
|
|
|
|
```text
|
|
|
|
Blockhash: 11111111111111111111111111111111
|
|
|
|
Signers (Pubkey=Signature):
|
|
|
|
AjTz9EX6vXB6EboKpFm7SwrbDannb6icjvEE632D3rfi=3uZndChSmPoYfaCihC993E7EAHKDsuu53Ge6Dk1K6ULwhJkgcgiHNm9J1Geqq2azW6PKxQTFjC8rMm5bGxRcYWA
|
|
|
|
|
|
|
|
{"blockhash":"11111111111111111111111111111111","signers":["AjTz9EX6vXB6EboKpFm7SwrbDannb6icjvEE632D3rfi=3uZndChSmPoYfaCihC993E7EAHKDsuu53Ge6Dk1K6ULwhJkgcgiHNm9J1Geqq2azW6PKxQTFjC8rMm5bGxRcYWA"]}
|
|
|
|
```
|
|
|
|
|
|
|
|
### An Example of Failure
|
|
|
|
|
|
|
|
To simulate an error the [verification step](#verify-the-signature) is repeated,
|
|
|
|
but with a corrupted _signature_ (the last letter is changed from "A" to "B").
|
|
|
|
|
|
|
|
Command
|
|
|
|
|
|
|
|
```text
|
|
|
|
solana transfer 11111111111111111111111111111111 0 --sign-only --from AjTz9EX6vXB6EboKpFm7SwrbDannb6icjvEE632D3rfi \
|
|
|
|
--signer AjTz9EX6vXB6EboKpFm7SwrbDannb6icjvEE632D3rfi=3uZndChSmPoYfaCihC993E7EAHKDsuu53Ge6Dk1K6ULwhJkgcgiHNm9J1Geqq2azW6PKxQTFjC8rMm5bGxRcYWB \
|
|
|
|
--blockhash 11111111111111111111111111111111 --fee-payer AjTz9EX6vXB6EboKpFm7SwrbDannb6icjvEE632D3rfi
|
|
|
|
```
|
|
|
|
|
|
|
|
Output (Error)
|
|
|
|
|
|
|
|
```text
|
|
|
|
Error: BadParameter("Transaction construction failed, incorrect signature or public key provided")
|
|
|
|
```
|
|
|
|
|
2019-12-09 15:35:18 -08:00
|
|
|
## Checking Account Balance
|
|
|
|
|
|
|
|
All that is needed to check an account balance is the public key of an account.
|
|
|
|
To retrieve public keys securely from a paper wallet, follow the
|
2019-12-19 20:59:07 -05:00
|
|
|
[Public Key Derivation](#public-key-derivation) instructions on an
|
2019-12-09 15:35:18 -08:00
|
|
|
[air gapped computer](https://en.wikipedia.org/wiki/Air_gap_\(networking\)).
|
2019-12-19 20:59:07 -05:00
|
|
|
Public keys can then be typed manually or transferred via a USB stick to a
|
2019-12-09 15:35:18 -08:00
|
|
|
networked machine.
|
|
|
|
|
|
|
|
Next, configure the `solana` CLI tool to connect to a particular cluster:
|
|
|
|
|
|
|
|
```bash
|
2020-02-19 14:04:34 -07:00
|
|
|
solana config set --url <CLUSTER URL> # (i.e. http://devnet.solana.com:8899)
|
2019-12-09 15:35:18 -08:00
|
|
|
```
|
|
|
|
|
|
|
|
Finally, to check the balance, run the following command:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
solana balance <PUBKEY>
|
|
|
|
```
|
|
|
|
|
2019-12-19 20:59:07 -05:00
|
|
|
In order to check a list of public keys quickly, append public keys to a file,
|
|
|
|
one per line, like so:
|
2019-12-09 15:35:18 -08:00
|
|
|
|
|
|
|
`public_keys.txt`
|
|
|
|
```bash
|
|
|
|
7hTw3XhprjT2DkVxVixtig9eZwHTZ2rksTSYN7Jh5niZ
|
|
|
|
9ufAiSyboCZmmEsoStgLYQfnx9KfqP1ZtDK8Wr1j8SJV
|
|
|
|
# ...
|
|
|
|
```
|
|
|
|
|
|
|
|
And run the following command:
|
|
|
|
```bash
|
|
|
|
while read PUBLIC_KEY;
|
|
|
|
do echo "$PUBLIC_KEY: $(solana balance "$PUBLIC_KEY" | tail -n1)";
|
|
|
|
done < public_keys.txt
|
|
|
|
```
|
|
|
|
|
2019-12-05 21:12:41 -05:00
|
|
|
## Running a Validator
|
|
|
|
|
|
|
|
In order to run a validator, you will need to specify an "identity keypair"
|
|
|
|
which will be used to fund all of the vote transactions signed by your validator.
|
|
|
|
Rather than specifying a path with `--identity-keypair <PATH>` you can use the
|
|
|
|
`--ask-seed-phrase` option.
|
|
|
|
|
|
|
|
```bash
|
|
|
|
solana-validator --ask-seed-phrase identity-keypair --ledger ...
|
|
|
|
|
|
|
|
[identity-keypair] seed phrase: 🔒
|
|
|
|
[identity-keypair] If this seed phrase has an associated passphrase, enter it now. Otherwise, press ENTER to continue:
|
|
|
|
```
|
|
|
|
|
|
|
|
The `--ask-seed-phrase` option accepts multiple keypairs. If you wish to use this
|
|
|
|
input method for your voting keypair as well you can do the following:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
solana-validator --ask-seed-phrase identity-keypair voting-keypair --ledger ...
|
|
|
|
|
|
|
|
[identity-keypair] seed phrase: 🔒
|
|
|
|
[identity-keypair] If this seed phrase has an associated passphrase, enter it now. Otherwise, press ENTER to continue:
|
|
|
|
[voting-keypair] seed phrase: 🔒
|
|
|
|
[voting-keypair] If this seed phrase has an associated passphrase, enter it now. Otherwise, press ENTER to continue:
|
|
|
|
```
|
|
|
|
|
|
|
|
Refer to the following page for a comprehensive guide on running a validator:
|
|
|
|
{% page-ref page="../running-validator/README.md" %}
|
|
|
|
|
|
|
|
## Delegating Stake
|
|
|
|
|
|
|
|
Solana CLI tooling supports secure keypair input for stake delegation. To do so,
|
|
|
|
first create a stake account with some SOL. Use the special `ASK` keyword to
|
|
|
|
trigger a seed phrase input prompt for the stake account and use
|
2020-02-21 14:55:53 -07:00
|
|
|
`--keypair ASK` to securely input the funding keypair.
|
2019-12-05 21:12:41 -05:00
|
|
|
|
|
|
|
```bash
|
2020-02-21 14:55:53 -07:00
|
|
|
solana create-stake-account ASK 1 --keypair ASK
|
2019-12-05 21:12:41 -05:00
|
|
|
|
|
|
|
[stake_account] seed phrase: 🔒
|
|
|
|
[stake_account] If this seed phrase has an associated passphrase, enter it now. Otherwise, press ENTER to continue:
|
|
|
|
[keypair] seed phrase: 🔒
|
|
|
|
[keypair] If this seed phrase has an associated passphrase, enter it now. Otherwise, press ENTER to continue:
|
|
|
|
```
|
|
|
|
|
2020-02-21 14:55:53 -07:00
|
|
|
Then, to delegate that stake to a validator, use `--keypair ASK` to
|
2019-12-05 21:12:41 -05:00
|
|
|
securely input the funding keypair.
|
|
|
|
|
|
|
|
```bash
|
2020-02-21 14:55:53 -07:00
|
|
|
solana delegate-stake --keypair ASK <STAKE_ACCOUNT_PUBKEY> <VOTE_ACCOUNT_PUBKEY>
|
2019-12-05 21:12:41 -05:00
|
|
|
|
|
|
|
[keypair] seed phrase: 🔒
|
|
|
|
[keypair] If this seed phrase has an associated passphrase, enter it now. Otherwise, press ENTER to continue:
|
|
|
|
```
|
|
|
|
|
|
|
|
Refer to the following page for a comprehensive guide on delegating stake:
|
|
|
|
{% page-ref page="../running-validator/validator-stake.md" %}
|
|
|
|
|
2019-11-26 23:56:11 -05:00
|
|
|
---
|
|
|
|
|
2019-12-05 21:12:41 -05:00
|
|
|
{% page-ref page="../api-reference/cli.md" %}
|