Bitcoin Full Node on RBP3

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

Note_2

Things you need:

  • 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

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

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

More about it here.

Connect & secure Raspberry

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

π ~> passwd
π ~> exit

Use keys to auth with ssh

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

 ~> 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…

π ~> 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

# 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)

# 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

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

π ~> 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)

π ~> 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

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 🐡

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

Run

π ~> bitcoind
Bitcoin server starting

Make sure it works

π ~> 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…

π ~> 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…

Run on reboot

π ~> 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

Other thingies

Add some scripts to make the sync bearable

# 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

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?

Happy?

Other Guides…

  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.

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