Zcash Shielded Transactions on the Raspberry Pi

If you are running a home node, then a single-board computer is an excellent choice due to its low power draw and the fact you can dedicate the low-cost machine to a single purpose. The Raspberry Pi, in particular, has been popularised for cryptocurrency nodes by the likes of the Casa Node and RaspiBlitz which constitute full Bitcoin/Litecoin and Lightning nodes.

When Sapling was announced with its dramatic improvements in proving speed and memory requirements there were many wondering whether it would now be possible to send shielded transactions on a Raspberry Pi.

In the upcoming v2.0.5 release of zcashd, the full-node software for Zcash, there is support for cross-compiling for the ARMv8 (aarch64) architecture. That means, with a few caveats, it’s now possible to run zcashd on the Raspberry Pi and also other ARM-based single board computers that have 64-bit CPUs.

Zcashd running on Raspberry Pi

In practice, the primary issue is now not one of the memory requirements for creating a zero-knowledge proof, but rather the bottleneck is the initial syncing and verification of the blockchain. While you can use the Pi to run a Zcash node as detailed below, due to its minimal resources, it isn’t the best-suited device, and there are plenty of alternatives that better suit the purpose for a little extra listed at the end of the post.

Choosing an Operating System

This cross-compiled version of zcashd will only run on a 64-bit ARMv8, also known as aarch64 architecture. That means you’ll need a 64-bit operating system. Raspian, the official operating system for the Raspberry Pi only runs in 32-bit mode and so is not suitable. However, a number of distros have a 64-bit OS for the Pi3 such as Fedora, openSuse and Arch Linux.

For the Pi3 Model B+, there is an official release of Ubuntu 18.04.2 (the current LTS release) which may be downloaded by following the link titled Ubuntu 18.04 Raspberry Pi3 (64-bit ARM) preinstalled server image. Due to official support for Debian, it is recommended to choose a Debian-based distro with the latest Ubuntu LTS being a perfect choice, especially as there are currently no official Debian Pi3 images. For those wanting Debian on the Raspberry Pi3 (not +) the following Debian Stretch based distro works well.

Hard Drive

The current Zcash blockchain on mainnet is around 21GB. While you can run this on a suitably sized micro SD card a solid state hard drive (SSD) connected via USB is recommended. On the Pi, you will need to use a swap partition or swap file which is generally considered a bad idea on a micro SD card due to excessive wear. You can place the swap file on the external hard drive or if using a micro SD card an external USB stick. Whatever method you choose for swap, it’s going to be very slow.

Assuming you are using an external SSD, once connected to an available USB port, you will need to mount it as we’ll use this as the basis for both our swap file and also the zcash data directory. Full details to accomplish this are available here.

Once mounted, configure a 2GB swap file on the mounted external SSD by following the tutorial here. For example, if you mounted your external SSD drive at /mnt/zcash-disk then create the swap file using sudo fallocate -2 G /mnt/zcash-disk/swapfile. Follow the remainder of the tutorial to enable the swap file.

Cross-compiling zcashd for ARMv8

Cross-compiling means you build on one machine (in this case using an x86_64/amd64 architecture) and then use the result on the target machine (running the aarch64 architecture). For existing Debian-based Linux users, simply add a single dependency and then build using the following commands, which will output the completed binaries to the /src/ directory:

apt-get install g++-aarch64-linux-gnu
HOST=aarch64-linux-gnu ./zcutil/build.sh -j$(nproc)

Alternitavely, for a Docker solution (credit to Ian Munoz for original instructions):

docker run -it --rm -v /tmp:/tmp debian:latest

This creates a container with the latest version of Debian (currently 9.8). A bind mount is created mapping the /tmp directory on the host machine to the /tmp directory on the container. Adjust the local directory to suit your needs, as this is where the compiled binaries will be placed when using the commands below. The additional options mean the container will run in interactive mode with a terminal, and the container will be destroyed when you stop it. Once started you should arrive at the terminal where you can enter the following commands:

apt-get update
apt-get upgrade -y
apt-get install -y build-essential pkg-config libc6-dev m4 g++-multilib autoconf libtool ncurses-dev unzip git python python-zmq zlib1g-dev wget curl bsdmainutils automake
apt-get install -y g++-aarch64-linux-gnu
git clone https://github.com/zcash/zcash.git
cd zcash/
HOST=aarch64-linux-gnu ./zcutil/build.sh -j$(nproc)
mkdir /tmp/aarch64-zcash/
cp ./src/zcash-cli ./src/zcashd ./zcutil/fetch-params.sh /tmp/aarch64-zcash/

This will build the latest version of zcashd on master. Alternatively, you may wish to target a single release by running e.g. git checkout v2.0.5 once it is available before completing the build.

If using the instructions above, the cross-compiled binaries will be in an aarch64-zcash directory in the /tmp directory (or wherever you specified) on the host system. Copy these files (zcash-cli, zcashd and fetch-params.sh) over to your Raspberry Pi using a method of your choice e.g. scp or SFTP. They can live anywhere on the system but usr/bin/local is a good choice if you want them to be in your existing PATH.

On the Pi run zcashd --version (or ./zcashd --version from the same directory if the binaries are not in your PATH) to ensure that everything is working. If when running you get an error, you might need the additional dependency apt-get install libgomp1 and ensure the user has permission to execute the binaries.

If you are running an alternate OS such as one based on Debian Stretch and see version GLIBC_2.25' not found or similar you will need to ensure you complete the cross-compile on a similarly versioned distro and not, say on the latest version of Ubuntu, as this will compile with updated dependencies that are not available for your OS.

Running zcashd on the Pi

To run zcashd, you first need to download the parameters required for sending and validating shielded transactions. These parameters are currently around 1.7GB in size and only need to be downloaded once. To do so, run the fetch-params.sh script copied over previously which will download the parameters to the ~/.zcash-params directory.

You’ll also need a zcash.conf file. See the docs for a full explanation but the following minimal file will get you started, ensuring that you specify the path to your mounted hard drive as the datadir. Create this file at ~/.zcash/zcash.conf:

addnode=mainnet.z.cash
datadir=/mnt/zcash-disk

Now you can run zcashd to begin the sync and run in the background with the command zcashd --daemon. To monitor the progress use the command zcash-cli getinfo which will show you the progress of the sync. You’ll likely hit issues with available RAM after a few tens of thousands of blocks that will cause zcashd to crash. It may be possible to complete by tweaking some configuration options and having a lot of patience, but it is likely much simpler and definitely faster to perform the initial blockchain sync on an alternate machine and then simply copy the data directory to the Pi (you need the blocks and chainstate directories).

To get improved sync performance without copying over the data directory from an alternate machine consider some of the Pi alternatives with more RAM.

Sending a Sapling Transaction

Once you have either synced or copied the blockchain data to the Pi, it is now possible to send a fully shielded Sapling transaction. Before doing so we’ll benchmark the device for Sapling spends and outputs. A typical transaction will have a single spend (consumed note) and two shielded outputs (created notes) as most transactions include some change. Sapling spends consume the most resources, and on a high-end machine will take a couple of seconds, but obviously, this figure is inflated on a Pi. The following commands will complete five Sapling spends that can be averaged:

zcash-cli zcbenchmark createsaplingspend 5

The result on a Pi Model 3 or 3B+ will typically be around 15 seconds.

Sapling outputs are much lighter to generate typically taking around 2 seconds on a Pi.

zcash-cli zcbenchmark createsaplingoutput 5

You can use these numbers to estimate how long your fully shielded Sapling transactions will take, e.g. one input to two outputs would be around 19 seconds. This isn’t exactly the couple of seconds you’ll get on a faster machine but perfectly acceptable on such a low-powered device. Increasing the number of input notes (say consuming a lot of small input notes in a larger transaction) will increase this figure accordingly.

For example, completing an example fully shielded transaction on the Pi results in the following, with the transaction taking 19.49 seconds to complete.

$ ./zcash-cli z_getoperationresult
[
  {
    "id": "opid-c977082e-31f3-453b-af0c-378ddd8e3777",
    "status": "success",
    "creation_time": 1556509623,
    "result": {
      "txid": "4175e2f1fd090d543362755c135ac0fbdfd7a0bb9399359278a91c416b81a78f"
    },
    "execution_secs": 19.491537137,
    "method": "z_sendmany",
    "params": {
      "fromaddress": "zs1lnkmwcvxgm9k2fsarmnxn0lry83m427n0mulnvjddse9rp8se94fmx6ge5wjq78atjspqtmm4us",
      "amounts": [
        {
          "amount": 0,
          "address": "zs10m00rvkhfm4f7n23e4sxsx275r7ptnggx39ygl0vy46j9mdll5c97gl6dxgpk0njuptg2mn9w5s"
        }
      ],
      "minconf": 1,
      "fee": 0.0001
    }
  }
]

Note that if you want to avoid sending via the command line on the Pi, then it is recommended to run Zec Wallet on your host machine and to use port forwarding to your Pi node.

Alternatives to the Raspberry Pi

The main limitation of the Pi is, of course, its 1GB of RAM. So while it is possible, it might not be the best choice for a zcashd node. Users on the Zcash forum have reported successes with both the Pine64 Rock64Pro and Odroid C2 which contain 4GB and 2GB of RAM respectively.

Just released, the Odroid N2 looks like a great solution with 4GB of RAM. The newly released Jetson Nano Developer Kit from Nvidia (also 4GB of RAM) is also worth a look. The NanoPC-T3 Plus is another option but for the simplest/best experience choose a board with 4GB of RAM. Just make sure before purchase that the CPU supports the ARMv8 architecture.

Again, you’ll need a 64 bit OS for these devices and Ubuntu Server or Armbian are recommended. As Armbian is based on Debian Stretch you’ll want to cross-compile on a Debian Stretch release to avoid dependency issues.

Whatever you try, post your sucesses and failures to the Zcash forum.

Updated with benchmarks for popular boards

| ARM Board              | Sapling Spend | Sapling Output |
| ---------------------- | ------------- | -------------- |
| Odroid C2              | 12.25         | 1.79           |
| Raspberry Pi 3B        | 15.64         | 2.29           |
| Raspberry Pi 3B+       | 14.71         | 1.99           |
| Odroid N2              | 6.46          | 0.98           |
| Nvidia Jetson Nano     | 9.73          | 1.43           |
| Pine64 RockPro64 (4GB) | 7.93          | 1.13           |