Cold Wallets


When security of funds is critical, it is a best practice to split your balance between multiple wallets:

  1. One or more hot wallets to handle daily user deposits/withdraws.
  2. One or more cold wallets to securely store Nano in an offline environment.

A cold wallet manages private keys that have never been on a network-enabled computer.

This guide extends the concepts covered in External Private Key Management. It is advised that you read that section before continuing.

Operations done on the hot, online, insecure computer will be prefaced with (HOT). Operations done on the cold, offline, secure computer will be prefaced with (COLD).

Both the hot and cold computers need to have the rai_node software installed. The hot rai_node needs to be synced with the network; the cold rai_node by definition should not be synced as it never connects to the internet.

The typical work flow for a cold wallet is as follows:

  1. (HOT) Gather account and transaction data.
  2. Transfer this data (e.g. via USB stick) to the (COLD) secure offline computer.
  3. (COLD) Verify Head Block hash.
  4. (COLD) Generate and Sign new transaction data.
  5. Tranfer the signed transaction back to the (HOT) insecure online-computer.
  6. (HOT) Publish the signed transaction to the Nano Network.
  participant Network
  participant HOT
  participant COLD
  HOT->>Network: Get Data
  Network->>HOT: Data Response
  HOT-->>COLD: Offline Transfer
  COLD-->>COLD: Verify
  COLD-->>COLD: Generate & Sign
  COLD-->>HOT: Return Signed
  HOT->>Network: Publish Signed
  Note over COLD,HOT: Cold/Hot Wallet transfers are done<br />offline using USB Stick or similar.

Private Key Management

The process for external private key management in a cold wallet is very similar to external private key management for a hot wallet. The primary difference is that all signing commands (and thus information containing your private key) are isolated to a clean computer with no network connection.

This guide only works with Universal Blocks, not the deprecated legacy blocks.

(HOT) Account Information

Get account information by the account_info RPC Command

Request Format
curl -d '{
  "action": "account_info",
  "representative": "true",
  "account": "<YOUR_ACCOUNT>"
curl -d '{"action": "account_info", "representative": "true", "account": "xrb_3qb1qckpady6njewfotrdrcgakrgbfh7ytqfrd9r8txsx7d91b9pu6z1ixrg"}'
Success Response
  "frontier": "DC8EC06D1F32F97BD69BF59E3297563BD23779F72176A4FF553CFF52309C337E",
  "open_block": "2E1F5AD4BD2C840FD9DC3929ECE9EE6D0B4A8C870E45EDA11048DE91EC409165",
  "representative_block": "DC8EC06D1F32F97BD69BF59E3297563BD23779F72176A4FF553CFF52309C337E",
  "balance": "8900000000000000000000000",
  "modified_timestamp": "1524812177",
  "block_count": "105",
  "representative": "xrb_3rropjiqfxpmrrkooej4qtmm1pueu36f9ghinpho4esfdor8785a455d16nf"

(HOT) Balance Validation (Part 1)

We should always assume the (HOT) computer has been compromised, so cannot trust the balance returned by account_info. We must obtain the headblock's transaction data and independently confirm the block's hash on our (COLD) offline computer. On the (HOT) online computer, this information can be obtained by the block RPC Command.

Request Format
curl -d '{"action": "block", "hash": "{{HEADBLOCK}}"}'
curl -d '{"action": "block", "hash": "DC8EC06D1F32F97BD69BF59E3297563BD23779F72176A4FF553CFF52309C337E"}'
Success Format
{ "contents": "<CONTENTS>" }
Example Contents
  "type": "state",
  "account": "xrb_3qb1qckpady6njewfotrdrcgakrgbfh7ytqfrd9r8txsx7d91b9pu6z1ixrg",
  "previous": "829C33C4E1F41F24F50AB6AF8D0893F484E7078F0FA05F8F56CB69223E8EEE77",
  "representative": "xrb_3rropjiqfxpmrrkooej4qtmm1pueu36f9ghinpho4esfdor8785a455d16nf",
  "balance": "8900000000000000000000000",
  "link": "616349D5A5EBA49A73324EF29044B65E13644EC182FFC1ACA4371F897EFF22AA",
  "link_as_account": "xrb_1rd5b9ctdtx6mbsm6mqkk34deqimej9e51qzr8pcafrzj7zhyaockuye93sk",
  "signature": "5058A5A1D371CE367D88DB232D398B33DF15FF95D84206986848F4165FFD9FB009B99D9DC6E90D2A3D96C639C7772497C6D6FFB8A67143AE9BB07DC49EB72401",
  "work": "5621a5a58ef8964a"

Below are a few important points to remember:

  • <CONTENTS> are returned as a stringified JSON object.
  • The type of the block is "state". This guide only covers on how to trustlessly process "state" blocks on an offline computer.

Transfer the response over to the (COLD) computer.

(COLD) Balance Validation (Part 2)

On the (COLD) computer, we need to verify the block hash. This allows us to trust the block's balance field enough to create a safe transaction.

Request Format
curl -d '{"action": "block_hash", "block": "<CONTENTS>"}'
curl -d '{"action": "block_hash", "block": "{\n    \"type\": \"state\",\n    \"account\": \"xrb_3qb1qckpady6njewfotrdrcgakrgbfh7ytqfrd9r8txsx7d91b9pu6z1ixrg\",\n    \"previous\": \"829C33C4E1F41F24F50AB6AF8D0893F484E7078F0FA05F8F56CB69223E8EEE77\",\n    \"representative\": \"xrb_3rropjiqfxpmrrkooej4qtmm1pueu36f9ghinpho4esfdor8785a455d16nf\",\n    \"balance\": \"8900000000000000000000000\",\n    \"link\": \"616349D5A5EBA49A73324EF29044B65E13644EC182FFC1ACA4371F897EFF22AA\",\n    \"link_as_account\": \"xrb_1rd5b9ctdtx6mbsm6mqkk34deqimej9e51qzr8pcafrzj7zhyaockuye93sk\",\n    \"signature\": \"5058A5A1D371CE367D88DB232D398B33DF15FF95D84206986848F4165FFD9FB009B99D9DC6E90D2A3D96C639C7772497C6D6FFB8A67143AE9BB07DC49EB72401\",\n    \"work\": \"5621a5a58ef8964a\"\n}\n"}'
Success Response
{ "hash": "DC8EC06D1F32F97BD69BF59E3297563BD23779F72176A4FF553CFF52309C337E" }

Using the responded hash on the (COLD) computer guarentees that the transaction we are about to create on the (COLD) computer will have a safe, expected outcome.

Lets consider the following scenarios where malicious software on the (HOT) computer modifies data:

  • You are creating a Send Transaction.
  • Malicious software alters the balance field of the head block to be lower than it actually is in an attempt to get you to send too much Nano to the destination address.
  • This alters the block's hash, but the malicious software could report the honest headblock's hash.

By independently computing the headblock's hash on the (COLD) computer, the generated transaction would be rejected by the network since the previous field references a non-existent block which is certainly not the headblock of your account.

Use the responded hash for the previous field in your new transaction. When computing final account balance, compute it relative to the balance field of the headblock on the (COLD) computer. Complete the rest of the block creation as described in section "External Private Key Management".

Once the block is created and signed on the (COLD) computer, transfer the contents over to the (HOT) computer. From the (HOT) computer, run the process command to broadcast the signed transaction to the network.