Building and Running the code without HSMs

Subzero can be used without HSMs. This is useful for evaluation purpose as well as development. The wallet is however not encrypted — Subzero's security model assumes you are using a HSM in your production setup.

The instructions in this page work with Mac OS X. Linux users can simply skip irrelevant parts. Windows users are advised to use a virtualization layer (e.g. Ubuntu inside VirtualBox).

The Core is compiled using cmake and gcc. The web server and GUI are built using gradle and run with Java. Since we don't have a HSM, we'll be using stub classes (included with Subzero) to successfully compile the code — HSM-specific steps will then be skipped.

Installing the tools and building the code

This section goes over the minimal set of tools needed to build and run Subzero. If you would like to develop and contribute to Subzero, we recommend installing Intellij IDEA for the Java piece and CLion for the C core.

(You can skip some of these steps if you prefer to use Docker instead. The command to build and run the Core is cd core; docker build -t subzero . && docker run -t -p 32366:32366 --name subzero subzero. In the future, we may provide additional docker files for running the GUI and web server).

# Open Terminal and install Homebrew
/usr/bin/ruby -e "$(curl -fsSL"

# install Java
brew update
brew cask install java

# note: if Mac OS X gives you a warning about unverified developers, you can go to the
# Security & Privacy settings and allow the action to take place.

# install cmake
brew install cmake

# install protobuf
brew install protobuf

# close + re-open the Terminal window for some changes to take effect

# clone the repo
git clone --recursive
cd subzero

# build the Java code
cd java
./gradlew build

# build the C code, using testnet transactions.
cd ../core
mkdir build
cd build
TARGET=dev CURRENCY=btc-testnet cmake ../

# create the wallets directory
sudo mkdir -p /data/app/subzero/wallets/
sudo chown $USER /data/app/subzero/wallets/
touch /data/app/subzero/wallets/.subzero_702e63a9

Running the servers and user interface

See also sample output.

# start the core (listens on port 32366 by default)
# when the Core starts, it runs several self checks. Some number of red lines is thus expected

# in a fresh Terminal tab, start the dev/demo server (listens on port 8080)
java -jar ./subzero/java/server/build/libs/server-1.0.0-SNAPSHOT.jar server

# in a fresh Terminal tab, open http://localhost:8080/.
open http://localhost:8080/

# start the GUI
java -jar ./subzero/java/gui/build/libs/gui-1.0.0-SNAPSHOT-shaded.jar

Your environment should look as following (from top left, going clockwise): the GUI, a web browser, and a Terminal.

Environment layout

Creating a wallet and signing your first transaction

By default, Subzero is configured to work with 2-of-4 signatures. Creating a wallet will therefore require 4 initialization and 4 finalization steps. Broadcasting a transaction will require 2 signatures.


On the web browser, click on "generate QR code" under Initialize a wallet. Unless if you set a wallet id, the QR code should be "EAAaAA==".

Init wallet: dev server

You can paste this code in the GUI, which will change the GUI to the approval step. note: the GUI currently does not support clipboard operations. You can instead use the Terminal tab to copy-paste data.

Init wallet: GUI

Type "yes" + [enter] to continue. A QR code is displayed, but you can also copy the data from the Terminal. You will want to save this response in TextEdit. In our case, the response was CnMKcQpv3trfyO6S55vO5PLtkpjakvPNzdOb+PLe0P3O5sft4tzb55Lp2tLd5N7Fydjs4MPZ8szcn5Lkm53dyc+ewcWSweDF2snP39ub/fny2v/v7ODI8uzA0M7+/8/8meDD0M7znO3vx+ub7+aS3Z3O+sDy. Since this response contains ciphertext, the data will be different each time.

Init wallet: GUI done

Before you can repeat the wallet initialization process 3 more times, you need to move the wallet file out of the way:

# In a fresh Terminal tab
cd /data/app/subzero/wallets
mkdir initialized
mv -n subzero-0.wallet initialized/subzero-0.wallet-1

Once you are done initializing the 4 shares, you'll have 4 files in /data/app/subzero/wallets/initialized:

Init wallet: 4 shares

And 4 responses in TextEdit:

Init wallet: 4 responses


You can now finalize each share. Using the Finalize a wallet section in the web browser, fill out each initialize response and click on "generate QR code". For reference, here is our data, but yours will differ:


Finalize wallet: dev server

You can now finalize each wallet file. You will have to, one-by-one, copy wallet files from /data/app/subzero/wallets/initialized to /data/app/subzero/wallets/ and move the result to /data/app/subzero/wallets/finalized/.

mv -n initialized/subzero-0.wallet-1 subzero-0.wallet

Finalize wallet: GUI

Type "yes" + [enter] to continue. Again, make sure you record each response. Our response was EnEKb3RwdWJEOE0xZE5YRzgycDhZZ2d5MVJYdHpXZExtR0h2cU04Q3B4d050b2NyRkppc1hmdjU4TjE3d2NlNGtvOGtKb3BjZXVxMVdTWHBVRUZKYlhGanpkVFVlVjNKaXpkWTZHRW1BMUVMOHc3ZFBqWA==.

Finalize wallet: GUI done

Move the wallet file out of the way and finalize the remaining 3 shares.

mv -n subzero-0.wallet finalized/subzero-0.wallet-1

Once you are done finalizing the 4 shares, you'll have 4 files in /data/app/subzero/wallets/finalized:

Finalize wallet: Finalized

And 4 more responses in TextEdit:

Finalize wallet: 4 responses

Reveal wallet xpubs

Using the 4 responses from the finalization step and the web browser, you can get the extended public keys (xpub prefix for mainnet and tpub prefix for testnet). These public keys can be used to derive addresses and send funds to the cold wallet.


Derive an address and send funds

Using the same 4 responses from the finalization step and the web browser, you can get addresses. Let's derive the first non-change address. In our case, we get 2NF3qdAFLNTvC8C7kqbccndZzqU22uFAr8Z.

Derive wallet address

We can send funds to this address and then use our wallet shares to sign a transaction which moves the funds out. For testnet addresses, we can use a faucet, which is a free service available to Bitcoin developers to get testnet coins.

We can then see our transaction on block explorer.

Sign a transaction

The server component of Subzero currently does not perform any kind of wallet or UTXO management. We must therefore provide the inputs and desired outputs. For our first transaction, we'll use the funding transaction as our sole input and send all the funds (minus the fee) to the gateway.

Using the web browser, we get the following signing request EAAqTQovCiAbDUIgtchXulYyyEGL9KseDnkTwZzXuWfuVMZv5Wb9zRABGLTdpAQiBBAAGAASDQiU0J4EEAIaBBAAGAAYACIAKQAAAAAAAAAA.

First transaction

We'll need to use any two wallet shares to sign this transaction.

mv -n finalized/subzero-0.wallet-1 subzero-0.wallet

SignTx GUI

Resulting in a signing response. Repeat the process with another wallet share to get two responses (our threshold).


Use the web browser to merge these signatures into a transaction.

Final transaction

Our final transaction is:


We used to broadcast this transaction.