Bitcoin Full Node on RBP3

Damian Mee
10 min readMay 23, 2017

--

This guide is obsolete. See the revised version for the newest Raspbian Stretch & Bitcoin v0.15.1.

This guide assumes you’re on MacOS, comfortable with terminal and want to run a headless Bitcoin Full Node on Raspberry Pi 3 and set it up w/o attaching any peripherals to RBP.

The following 3 cases will be covered:

  1. Bitcoin Node (follow 🐢),
  2. Bitcoin Node only signalling for UASF BIP148 and BIP149 (follow 🐡),
  3. Bitcoin Node enforcing UASF BIP148 starting August 1st (follow 🐰).

Note

All lines starting with  are run on MacOS. All lines starting with π are run on Raspberry Pi 3.

Note_2

The initial sync will take around 5–6 weeks (as of May 2017), so if you plan on enforcing BIP148 for your transactions, make sure to start it early enough for the sync to complete.

Things you need:

  • Raspberry Pi 3;
  • MicroSD card (200GB+) — make sure it’s big enough to store entire Bitcoin Blockchain (~140GB as of May 2017) and some fluff (~2GB) — note that the more free space you have on it, the longer your SD card will live;
  • a way to plug the micro SD card into your MacBook;
  • ethernet cable;
  • a router with a spare ethernet port.

Prepare SD card

Get Raspbian Lite image

Either via torrent or by abusing Raspberry Pi Foundation servers.

Put image on the SD card

# extract .img file from .zip archive
 ~> unzip 2017-04-10-raspbian-jessie-lite.zip

Plug the SD card into your computer and run below to identify the disk of your SD card:

 ~> diskutil list | grep external

Assuming it’s /dev/disk2:

# Unmount it
 ~> diskutil unmountDisk /dev/disk2
# Copy image to the SD card
 ~> sudo dd bs=1m if=2017-04-10-raspbian-jessie-lite.img of=/dev/disk2

For other OSs see here.

Enable ssh

Starting with Raspbian 2016–11–25 SSH is disabled by default. To enable it, a file named ssh needs to be created in the root of the SD card.

 ~> diskutil mountDisk /dev/disk2
 ~> touch /Volumes/boot/ssh
 ~> diskutil unmountDisk /dev/disk2

More about it here.

Connect & secure Raspberry

Once above is done, put the card into your Raspberry, plug it into the router and power it up.

After a minute or two it should boot up. Now it’s time to find its IP address.

There are multiple ways to do that, the easiest one would probably be logging into your router interface (ex. https://192.168.1.1) and trying to find it there.

If that doesn’t work you can also try:

# MAC prefix 'b8:27:eb:' is reserved for RBP Foundation
# see more: http://hwaddress.com/?q=B827EB000000
 ~> arp -a | grep 'b8:27:eb'

Or, if that doesn’t work, you can try nmapping your local network for open 22/tcp ports:

 ~> nmap -A 192.168.0-1.* -p T:22 --open

Assuming the IP of your Pi is 192.168.1.102, ssh to it (default password: raspberry):

 ~> ssh pi@192.168.1.102

Change user password

If you’d rather decrease the chances of your Pi joining the IoS party, change your password right away:

π ~> passwd
π ~> exit

Use keys to auth with ssh

Now that we’ve located the RBP and changed its password, let’s make things more secure.

I use Ed25519 keys and I strongly encourage you to do the same. Here’s an easy why & how to switch guide. That being said, you can pass a path to any key in the command below:

 ~> ssh-copy-id -i ~/.ssh/id_ed25519.pub pi@192.168.1.102

Next we need to disable password authentication. Either manually:

# edit ssh daemon config file
π ~> sudo nano /etc/ssh/sshd_config
# Find `#PasswordAuthentication yes` & below it add:
PasswordAuthentication no
# To save and exit press ^x + y + enter

Or using a oneliner:

π ~> sudo sed -i '/#PasswordAuthentication yes/a PasswordAuthentication no' /etc/ssh/sshd_config

Listen to ssh-audit.py

It’s a good tool that offers good advice. If you want to see recommendations it gives, run:

 ~> git clone git@github.com:arthepsy/ssh-audit.git
 ~> cd ssh-audit
 ~> ./ssh-audit.py 192.168.1.102

I won’t go into details here, but to follow its recommendations put this into /etc/ssh/sshd_config file on RBP3:

# make sure these are in the file and NOT commented out:
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
# make sure these are either gone or commented out:
#HostKey /etc/ssh/ssh_host_dsa_key
#HostKey /etc/ssh/ssh_host_ecdsa_key
# add the below lines
KexAlgorithms curve25519-sha256@libssh.org
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com

For Termius to work on mobile, you need to add diffie-hellman-group-exchange-sha256 to KexAlgorithms and hmac-sha-256 to MACs 😭.

For ConnectBot to work on mobile you only need to add hmac-sha2-512 to MACs 😢, as it supports Ed25519 curves.

Reload config of the ssh daemon:

π ~> sudo service ssh reload

Note: If you disconnect now you will need to remove line containing 192.168.1.102 from ~/.ssh/known_hosts on your Mac before connecting again.

Configure the Raspberry

Localization, Time Zone, etc…

Run the below and feel free to play with the wizard there. You might want to change time zone and WiFi country. Also, “expanding the filesystem” is no longer necessary, as it happens automatically on the first boot (ref: scroll this to 2016–05–10).

π ~> sudo raspi-config# And if it didn't ask you to, run:
π ~> sudo reboot

Get all the shiny updates

π ~> sudo apt-get update
π ~> sudo apt-get upgrade

Disable SWAP

Constant writing to an SD card can kill it in 30 days (according to the internet), so to minimize writes let’s:

# disable SWAP
π ~> sudo swapoff --all
# remove package that manages SWAP altogether
π ~> sudo apt-get remove dphys-swapfile
# I had some orphans left and this helped
π ~> sudo apt-get autoremove

Use WiFi instead (optional)

Since RBP3 has WiFi, and ethernet cables are so 90’s, let’s switch to WiFi instead:

# gotta do it as root
π ~> sudo su
# will generate network={} structure and save it to the right place
π (root)~> wpa_passphrase "SSID" "password" >> /etc/wpa_supplicant/wpa_supplicant.conf
# exit the root shell
π (root)~> exit
# Run to make Pi acknowledge changes
π ~> sudo wpa_cli reconfigure

After couple of seconds Pi, should automatically connect to the specified network. To find the new IP you can:

π ~> ip a show wlan0 | grep inet
inet 192.168.1.112/24 brd 192.168.0.255 scope global wlan0
inet6 fe80::9ac9:a0:e042:2da0/64 scope link

Or…

π ~> hostname -I
192.168.1.112

In both cases above the IP is 192.168.1.112, so:

π ~> exit
 ~> ssh pi@192.168.1.112

If that succeeded you can get rid of the ethernet cable and from now on just use 192.168.1.112.

Whether you followed this step or not, everything that follows remains the same.

Finally, the good stuff

The below steps are mostly, but loosely, based on the official UNIX BUILD NOTES.

Dependencies

Before we start, we need to install all required dependencies.

π ~> sudo apt-get install git build-essential libtool autotools-dev automake pkg-config libssl-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-program-options-dev libboost-test-dev libboost-thread-dev libminiupnpc-dev libzmq3-dev jq

Get Bitcoin Core

For 🐢 and 🐡 go to https://github.com/bitcoin/bitcoin/branches and see what’s the newest non-dev branch. As of May 2017 it’s 0.14, so:

π ~> cd ~# use https instead of ssh to avoid adding rbp3 key to gh account
π ~> git clone -b 0.14 https://github.com/bitcoin/bitcoin.git

For 🐰 run:

π ~> cd ~
π ~> git clone -b 0.14-BIP148 https://github.com/UASF/bitcoin.git

Berkeley DB (optional)

This very specific version (4.8) of Berkeley db is still needed if you want to have your client with wallet capabilities.

π ~> BITCOIN_ROOT=$(pwd)/bitcoin
π ~> BDB_PREFIX="${BITCOIN_ROOT}/db4"
π ~> mkdir -p $BDB_PREFIX
π ~> wget 'http://download.oracle.com/berkeley-db/db-4.8.30.NC.tar.gz'
π ~> echo '12edc0df75bf9abd7f82f821795bcee50f42cb2e5f76a6a281b85732798364ef db-4.8.30.NC.tar.gz' | sha256sum -c
# -> db-4.8.30.NC.tar.gz: OK
π ~> tar -xzvf db-4.8.30.NC.tar.gzπ ~> cd db-4.8.30.NC/build_unix/
π ~> ../dist/configure --enable-cxx --disable-shared --with-pic --prefix=$BDB_PREFIX
π ~> make install

Build Bitcoin Core

π ~> cd $BITCOIN_ROOTπ ~> ./autogen.sh# run this if you want wallet or…
π ~> ./configure LDFLAGS="-L${BDB_PREFIX}/lib/" CPPFLAGS="-I${BDB_PREFIX}/include/" CXXFLAGS="--param ggc-min-expand=1 --param ggc-min-heapsize=32768" --enable-cxx --without-gui --disable-shared --with-pic --enable-upnp-default
# …this if you don’t
π ~> ./configure CXXFLAGS="--param ggc-min-expand=1 --param ggc-min-heapsize=32768" --enable-cxx --without-gui --disable-shared --with-pic --enable-upnp-default --disable-wallet
# this might take a short forever - ~1.5 hr
π ~> make check
π ~> sudo make install

Configure

Probably the best way to get a well optimised ~/.bitcoin/bitcoin.conf file is to use the generator that Jameson Lopp was kind enough to create.

That being said, here’s the stuff you need to put there:

daemon=1
dbcache=100
maxorphantx=10
maxmempool=50
maxconnections=40
maxuploadtarget=5000
upnp=1

I would recommend against node pruning, however if you don’t have a big enough SD card, add prune=N to the config file. For example on a 64GB card you could set it to 42GB with:

prune=42000

Signal UASF 🐡

To just signal support for both BIPs add the following lines to the config file:

uacomment=BIP8
uacomment=UASF-SegWit-BIP149
uacomment=UASF-SegWit-BIP148

Run

π ~> bitcoind
Bitcoin server starting

Make sure it works

It might take a few minutes to start. You can watch progress by running:

π ~> tail -f ~/.bitcoin/debug.log

And here’s a couple of other handy commands that you can use later:

π ~> bitcoin-cli getinfo
π ~> bitcoin-cli getnetworkinfo
π ~> bitcoin-cli getwalletinfo
π ~> bitcoin-cli getblockchaininfo
π ~> bitcoin-cli getpeerinfo

Exposing port to the outside world…

In previous steps, MiniUPnP has already been compiled-in and enabled, so let’s check if your node is reachable from the outside with:

π ~> curl -s https://bitnodes.21.co/api/v1/nodes/me-8333/

If the response is {"success":true}, just skip to the next step.

Otherwise, there are still some things that can be done, but since they’re all very setup-specific, I will just list some ideas that might be worth pursuing:

  • Just wait a bit (UPnP is currently renewed every 20 minutes),
  • Restart node and wait until it boots up completely,
  • Make sure UPnP is enabled on the router,
  • Assign a permanent local IP to Raspberry Pi, and
  • Manually set up port forwarding (for port 8333),
  • Make sure your ISP provides you with a public IP (sometimes it might be possible to get a public/static IP as an additional service for a fee).
This is how a successful UPnP might look like

Note: If neither of the above worked your node will still connect to 8 peers and, from your perspective, will still be fully functional. The only difference being it will not be able to relay blocks and serve SPV wallets.

Now wait, and wait, and wait…

Now, that the node is running it will download and process the entire Bitcoin blockchain. This process will take over a month. Just leave it running and it will get there eventually.

Run on reboot

To avoid starting the node manually after each reboot add this to cron file:

π ~> which bitcoind/usr/local/bin/bitcoindπ ~> crontab -e# add this line to the end:
@reboot sleep 8; /usr/local/bin/bitcoind

The sleep 8 part is necessary to avoid this error:

Binding RPC on address 127.0.0.1 port 8333 failed.

Trusted Node

Once the sync completes your Node is ready for the grand cooperation with the excellent Samourai Wallet ❤️. To set it up just follow the simple guide here:

Other thingies

Add some scripts to make the sync bearable

While the sync takes place, to soothe your agitation, you can either monitor the progress value in ~/.bitcoin/bitcoin.conf file or append some aliases to either ~/.zshrc or ~/.bashrc:

# shows % of blocks processed
alias blocks='BLOCKS_FILE=~/.cache/blocks TOTAL=$(curl -s https://btc.blockr.io/api/v1/block/info/last | jq -r '.data.nb') CURRENT=$(bitcoin-cli getblockcount) && BLOCKSF=$(printf "%.5f%%" "$((100.0 * CURRENT / TOTAL))") && printf "%s → %s\n" "$(cat $BLOCKS_FILE)" $BLOCKSF && echo $BLOCKSF > $BLOCKS_FILE'
# turns logged `progress` into %
alias progress='PROG_FILE=~/.cache/progress PROG=$(grep UpdateTip ~/.bitcoin/debug.log T -n1 | cut -d " " -f 12 | cut -d = -f 2) PROGF=$(printf "%.2f%%" "$((PROG * 100))") && printf "%s → %s\n" "$(cat $PROG_FILE)" $PROGF && echo $PROGF > $PROG_FILE'

And run:

π ~> mkdir -p ~/.cache && echo "0%" > ~/.cache/{progress,blocks}

Now, running either progress or blocks on RBP will show output in the form of:

<value-when-previously-run> → <current-value>

Make ssh welcome message pretty

There’s no reason to see that awful block of text every time you log in. Making it prettier was inspired with stuff from here.

First, you need to create a file somewhere ex. /tmp/rbp-motd.sh and paste the below to it.

#!/bin/bash
logo="$(tput setaf 2)
.~~. .~~.
'. \ ' ' / .'$(tput setaf 1)
.~ .~~~..~.
: .~.'~'.~. :
~ ( ) ( ) ~
( : '~'.~.'~' : )
~ .~ ( ) ~. ~ $(tput sgr0)Raspberry Pi$(tput setaf 1)
( : '~' : ) $(tput sgr0)Bitcoin$(tput setaf 1)
'~ .~~~. ~'
'~'
$(tput sgr0)"
if [ `whoami` != "root" ]; then
echo "$logo"
echo "Run as sudo to update your motd."
else
echo "$logo" > /etc/motd
/etc/init.d/bootlogs
echo "Updated MOTD. Log in again to see the new logo."
fi

Then:

π ~> chmod a+x /tmp/rbp-motd.sh
π ~> sudo /tmp/rbp-motd.sh

Or, if you’re naïve enough to trust me:

π ~> wget -qO- https://gist.githubusercontent.com/meeDamian/9a98f7ae5aba2090872835e21217fb9e/raw/6631f475fd8fb55685921f411b3c39acb8bf1d87/na%25C3%25AFve-btc.sh | sudo sh

After either, just log in again, and you should be greeted with:

Improvements? Mistakes?

If you’ve found anything incorrect in this guide, or have an idea on how to improve it, feel free to either leave a comment, btc [AT] meedamian.com or @meeDamian me.

Happy?

If you want to get me a coffee or some AC time in the hot climate of Singapore 🇸🇬 you can send your appreciation to 1DamianM2k8WfNEeJmyqSe2YW1upB7UATx or https://paymentcode.io/+meedamian.

Other Guides…

This is a second guide in a series of planned:

  1. Litecoin Full Node on RBP3,
  2. Bitcoin Full Node (with or w/o BIP148 UASF 🙊) on RBP3,
  3. Add JoinMarket to Bitcoin Full Node,
  4. Add Lightning Network to #1,
  5. Proxy node traffic through TOR.

--

--

Damian Mee

Bitcoin. Lightning. Golang. Applied cryptography, not Blockchain. https://keybase.io/meedamian . PGP: D8CA 1776 EB92 6549 1D07 CE67 F546 ECBE A809 CB18