Custody Tool User Guide
Intro
In 2022, Chia built an internal solution for long-term storage of its prefarm. This tool has since been made public -- you can now lock your coins using the same solution as Chia used to lock its prefarm!
This guide will show you how to get started.
This tool was not originally developed with the broader ecosystem in mind. For this reason, the tool is provided as-is, with no guarantees of functionality, and with no support provided. Proceed with caution.
Before continuing, you might want to familiarize yourself with the following documents:
- Basic description of how the custody tool works
- Flow chart to visualize how the custody tool works
- CLI reference for all custody commands used in this tutorial
The custody tool uses many parameters, each of which is important. You are highly recommended to test the tool thoroughly on the testnet before deploying it on mainnet.
Install the custody tool
Requirements
- A synced full node (mainnet, testnet, or simulator)
- A synced Chia wallet
- Python 3.9 or greater (will not work with 3.8.x)
- Git command line tool
- Powershell 6 or greater (Windows only)
- Visual C++ Redistributable (Windows only)
Steps to install
- Clone the internal custody repository:
git clone https://github.com/Chia-Network/internal-custody.git
- Change to the new directory:
cd internal-custody
- Create a new virtual environment and then activate it:
- Windows
- Linux
- macOS
python -m venv venv
.\venv\Scripts\Activate.ps1
python3 -m venv venv
. ./venv/bin/activate
python3 -m venv venv
. ./venv/bin/activate
- Install the custody tool:
pip install --extra-index-url https://pypi.chia.net/simple/ chia-internal-custody
Note about pip warnings/errors
You may receive pip warning and/or dependency errors for blspy and/or clvm-tools-rs (see example below). These can be safely ignored.
ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
chia-blockchain 1.3.6.dev212 requires blspy==1.0.13, but you have blspy 1.0.9 which is incompatible.
chia-blockchain 1.3.6.dev212 requires clvm-tools-rs==0.1.9, but you have clvm-tools-rs 0.1.7 which is incompatible.
Successfully installed blspy-1.0.9 clvm-tools-rs-0.1.7 hsms-0.1.dev79
- Test your installation:
cic --help
If you get a usage statement, then cic
(Chia Internal Custody) has been installed properly.
Command Notes
The cic
commands for generating and signing keys are meant to be run from inside a Hardware Security Module (HSM). These commands are labeled as such.
An HSM is a physical/offline security solution for creating and using cryptographic signatures. While testing the custody tool, it is OK to run these commands from a normal computer. However, for maximum security while running the custody tool on Chia's mainnet, you are recommended to use an HSM (or a similar solution).
Most of the commands from this tutorial will not alter the blockchain. This includes all of the commands to be run from an HSM. Commands that will alter the blockchain are labeled as such.
Windows uses different line endings than Linux and MacOS. If you only plan to use Windows for both generating and signing spend bundles, this won't be a problem.
However, if you plan to generate your spend bundles on Windows and sign them using a Linux HSM, then you will need to modify the line endings before signing.
The easiest way to accomplish this is with dos2unix
.
This is not included with Windows, so you will need to download it from SourceForge.
The command to convert your spend bundles is then:
<path to dos2unix.exe> -o <path to spend bundle>
In general, any time you encounter signing errors, be sure the correct line endings are being used for the OS you are using to sign.
Generate keys
- These commands will not modify the blockchain. They will only create local files
- These commands should be run from an HSM
Before the custody singleton can be created, you must first create the public/private key pairs to be associated with it.
For this guide:
m
will initially be set to 2. This is security level, or "lock level" of the singleton. In other words, it's the number of keys required to sign for withdrawals and standard rekeys.n
will initially be set to 3. This is the maximum lock level of the singleton. In other words, it's the total number of keys that will be associated with the singleton.- Because
n
will initially be 3, we will create 3 keys now.m
andn
will be used later when setting up the singleton.
When creating and using these keys on mainnet, you should only store one key on each computer. Signing therefore requires copying an unsigned spend bundle to each individual computer that holds a key. This process is explained in detail later in the guide.
However, for this guide, we'll assume you're running an initial test using TXCH (and not actual XCH). In this case, it's OK to store multiple keys on the same computer while you get a feel for how the tool works.
The command used to generate "secret exponents" (private keys) is hsmgen
. This command is included with the cic
installation. It doesn't take any arguments; it merely generates a secret exponent and outputs it to the command line. However, we want to save the secret exponents to files, so we will use the >
key to redirect the output.
We will create three separate keys. These can be named anything. For this guide we'll simply use numbers.
- Create a directory to hold your keys and spend bundles:
mkdir keys_and_sb
- Change to the new directory:
cd keys_and_sb
- Create and redirect the secret exponents:
hsmgen > 1.se
hsmgen > 2.se
hsmgen > 3.se
- Use the
hsmpk
command to derive a public key from each secret exponent:
hsmpk $(cat 1.se) > 1.pk
hsmpk $(cat 2.se) > 2.pk
hsmpk $(cat 3.se) > 3.pk
As a result of running the hsmpk
command, a public key will be added to a new text file for each key (1.pk, 2.pk, and 3.pk).
If you are generating only one key per computer, you will need to copy the .pk (public key) files to the non-HSM machine, which will run a Chia node and be used for setting up the singleton in the next steps.
Initialize the singleton
The custody tool uses the Chialisp singleton primitive. This section will show you how to set up a custody singleton for testing.
Create the permanent layer
- This command will not modify the blockchain. It will only create a local file
- This command should be run from outside an HSM
The cic init
command will initialize the permanent layer of the singleton. None of this command's arguments may be changed later.
For this guide, we'll create an example singleton that uses the values listed in the table below. As a reminder, these settings correspond to those used in the flow chart.
Flag | Example Value | Description |
---|---|---|
-d | keys_and_sb | The directory where the keys and spend bundles will be stored. |
-wt | 600 seconds | Withdrawal Timelock -- the minimum number of seconds that must have elapsed since the last withdrawal, rekey or clawback before a withdrawal can be initiated. |
-pc | 1200 seconds | Payment Claw back -- the minimum number of seconds that must elapse after initiating a withdrawal before the withdrawal can be completed. Clawbacks are possible during this window. |
-rt | 300 seconds | Rekey Timelock -- when attempting to begin a standard rekey, this is the minimum number of seconds that must have elapsed since the last withdrawal, rekey or claw back. For a slow rekey, this amount gets added for each key less than m . |
-rc | 600 seconds | Rekey Claw back -- the minimum number of seconds that must elapse after initiating a rekey before the rekey can be completed. Claw backs are possible during this window. |
-sp | 900 seconds | Slow rekey Penalty -- this amount gets added to the Rekey Timelock when a slow rekey is being performed. |
- The singleton's time values are relative to when they're confirmed on chain
- The specific time values for this example were chosen for testing purposes only. In a mainnet custody solution, the values are typically measured in days (though still expressed in seconds)
Begin by initializing the singleton (run from the keys_and_sb
folder in this example):
cic init -d . -wt 600 -pc 1200 -rt 300 -rc 600 -sp 900
As a result of running the cic init
command, a binary file called Configuration (needs derivation).txt
will be created in the -d
location. This file will be used later to derive the root. Nothing has been added to the blockchain yet.
Create the non-permanent layer
- This command will not modify the blockchain. It will only create a local file
- This command should be run from outside an HSM
Now that you have keys and an underived configuration, you can run the derive_root
command, which will set up the singleton's non-permanent layer, with the following settings:
m
(current lock level)n
(maximum lock level)- The public keys that comprise
n
, expressed as a comma-separated list
This command includes an optional --configuration
flag to specify the name and location of the configuration file. By default, the command will look in ./Configuration (needs derivation).txt
.
If the --configuration
flag is not used, the .pk
(public key) files that you previously created also need to be in the current directory.
cic derive_root -pks "1.pk,2.pk,3.pk" -m 2 -n 3
You should receive the following response:
Custody rules successfully added to configuration
As a result of running this command, Configuration (awaiting launch).txt
will be created. The configuration now includes both the permanent and non-permanent layers.
Launch the singleton
- This command will modify the blockchain
- This command should be run from outside an HSM
In this step, you will run cic launch_singleton
, which will create the singleton on the blockchain.
In order to run this command, you will need to have at least 1 mojo in your wallet to create the singleton.
The launch_singleton
command also includes a recommended --fee
flag to specify a blockchain fee in mojos.
This fee is completely separate from the actual financing of the singleton, which will occur in a later step.
It is also possible to launch the singleton using one wallet and fund it with another -- think of the singleton as a brand new wallet.
Aside from the fees, the launch_singleton
command includes an optional --configuration
flag to specify the name and location of the configuration file. By default, the command will look in ./Configuration (awaiting launch).txt
.
Because this command modifies the blockchain, a synced wallet is required. To be sure your wallet is synced, run:
chia wallet show
If you have multiple fingerprints, select the one you want to use when launching the singleton. This wallet must contain at least 1 mojo, as well as sufficient funds to pay the fee if you are going to specify one.
The output of chia wallet show
must include Sync status: Synced
. If this wallet is not yet synced, then you will need to wait for it to finish syncing before continuing.
Once you have a synced wallet with sufficient funds, you can launch the singleton:
cic launch_singleton --fee 10000000
The output of this command should be:
Singleton successfully launched
The singleton will not be funded after running this command. It will have zero value until another command is run.
In addition, your wallet's transaction history will not show the fee being deducted, nor will it show the single mojo being deducted to create the singleton. This is because creating the singleton is not a standard transaction that your wallet will recognize. However, your wallet's Total Balance will show the correct amount after the transaction has been processed.
Congratulations, you have successfully launched the singleton! (You will need to wait for the next transaction block before it's added to the blockchain.) As a result of running this command, the configuration file's name has changed to Configuration (xxxxxx).txt
, where xxxxxx
is a hexadecimal value. For example:
(venv) ~/internal-custody/keys_and_sb$ ls
1.pk 1.se 2.pk 2.se 3.pk 3.se 'Configuration (74905b).txt'
Show the singleton
- This command will not modify the blockchain
- This command should be run from outside an HSM
At this point, the singleton should exist on the blockchain. However, it has not yet been funded. For now, let's view it.
Currently your local custody database does not know about the singleton.
Therefore, in order to view the singleton, you must first synchronize the localhost with the blockchain by running the sync
command.
The first time you run the sync
command, you need to specify the configuration file, which will then be copied into your config database.
For example:
cic sync -c "Configuration (<hex value>).txt"
Be sure to replace <hex value>
with the actual value from your configuration file, and make sure to put quotes around the file name because it contains a space.
This command does not produce any output. From now on, you don't need to specify the config file to synchronize your host with the blockchain. Instead, just run cic sync
.
To show the singleton's status without syncing, you can run cic show
. However, you will typically want to sync before showing the status. To do this, run cic sync -s
. For example:
cic sync -s
Current time: 1665072029 (10/07/2022, 00:00:29)
Config up to date: True
Singleton:
- launcher ID: b433146cc20ef0e3d962423ddb1c6868cd9691e099ae579ab2518d1cd983885c
- amount left: 0
- amount to claim: 0
Outstanding events:
PAYMENTS:
REKEYS:
To view the configuration, run cic show
and add the -c
flag.
To view the derivation info, run cic show
and add the -d
flag.
You can also add both flags.
For example:
~/internal-custody/keys_and_sb$ cic show -c -d
Current time: 1665072285 (10/07/2022, 00:04:45)
Config up to date: True
Singleton:
- launcher ID: b433146cc20ef0e3d962423ddb1c6868cd9691e099ae579ab2518d1cd983885c
- amount left: 0
- amount to claim: 0
Outstanding events:
PAYMENTS:
REKEYS:
Config:
- current root: 74905b06591f9d2e615d313d18cfbcbeffcaabe2e70ccdeafda783bacaae52ef
- withdrawal timelock: 600 seconds
- payment clawback period: 1200 seconds
- rekey cancellation period: 600 seconds
Derivation Info:
- lock level: 2
- max lock level: 3
- min keys to rekey: 1
- standard rekey timelock: 300 seconds
- slow rekey penalty: 900 seconds
- pubkeys:
- bls123813p8yljrhgskmgqeukg3x6mszh3xtqwwx35t4g6dt0mk2xecyj7elr0fhhrm8t3w7q5zhdelgjlgdspjqxvs
- bls123813uhsu0juw06z8vmtt5ncj6zcexmhtsfemvtj3jhv0vuxh9nqjdar59yh555muzrdpz2uflgzey3sgdnm8y9
- bls1238152jm50wh89tf70mwj4ncuukqcq6jqmf7pjgznm55c5qaggrvswzccwvsjgwmy9f4cvlx2j97kmh5uc2es6h
Here's how to interpret this output:
-
Singleton
launcher ID
: This shows the on-chain ID of your singletonamount left
: This is the current value of the singleton. For now it is zero because it has not yet been fundedamount to claim
: This is the number of mojos currently in the process of being withdrawn. The money is effectively sitting in escrow, and will be able to be withdrawn after the withdrawal timelock has been fulfilled
-
Outstanding events
PAYMENTS
: If there were a payment in progress, it would be shown hereREKEYS
: If there were a rekey in progress, it would be shown here
-
Config
current root
: Puzzlehash of the singleton as it is currently configuredwithdrawal timelock
: Number of seconds to wait before a withdrawal may be initiatedpayment clawback period
: Number of seconds to wait before a withdrawal may be completed. During this period, clawback is possiblerekey cancellation period
: Number of seconds to wait before a rekey may be completed. During this period, cancellation is possible
-
Derivation Info
lock level
: The number of keys required to sign for withdrawals and standard rekeysmax lock level
: The total number of keysmin keys to rekey
: The minimum number of keys that must sign for a slow rekeystandard rekey timelock
: The number of seconds since the last action before a standard rekey can be initiatedslow rekey penalty
: The number of seconds added as a penalty for all slow rekeys. This is in addition to the standard rekey timelocks that will vary depending on the number of keys signingpubkeys
: The keys themselves