Bitcoin Knots

We install Bitcoin Knots (opens in a new tab), an alternative client implementation of the Bitcoin network.

Preparations

The Bitcoin Knots application will run in the background as a daemon and use the separate user bitcoin for security reasons. This user does not have admin rights and cannot change the system configuration.

Create the bitcoin user/group

$SU addgroup -S bitcoin
$SU adduser \
    -S \
    -D \
    -H \
    -h /dev/null \
    -s /sbin/nologin \
    -G bitcoin \
    -g bitcoin \
    bitcoin

Add the user satoshi to the group bitcoin as well

$SU adduser satoshi bitcoin

Add the user bitcoin to the group tor

This allow the user bitcoin to use the control port and configure Tor directly

$SU adduser bitcoin tor

Create a symbolic link bitcoin to satoshi home

ln -s /var/lib/bitcoind "$HOME/.bitcoin"

Modify compiler flags

printf "%s\n" \
    "export CC=\"clang\"" \
    "export CXX=\"\${CC}++\"" \
    "export CFLAGS=\"-O3 -pipe -march=native -fPIE\"" \
    "export CXXFLAGS=\"\$CFLAGS\"" \
    "export LDFLAGS=\"-pie -Wl,--as-needed\"" \
    "export MAKEFLAGS=\"-j$(nproc)\"" \
    | $SU tee -a /etc/profile.d/defaults.sh
. /etc/profile.d/defaults.sh

Installation

In Bitcoin Knots >25.1 all spam filters are up to date

We download the latest Bitcoin Knots source code and compare this file with the signed and timestamped checksum. This is a precaution to make sure that this is an official release and not a malicious version trying to steal our money.

Download source code

  • Login as satoshi and change to a temporary directory which is cleared on reboot
cd /tmp
  • Set a temporary version environment variable to the installation
VERSION=26.1.knots20240325
  • Get the latest source code and signatures
wget https://bitcoinknots.org/files/${VERSION%%.*}.x/$VERSION/bitcoin-$VERSION.tar.gz \
    https://bitcoinknots.org/files/${VERSION%%.*}.x/$VERSION/SHA256SUMS \
    https://bitcoinknots.org/files/${VERSION%%.*}.x/$VERSION/SHA256SUMS.asc

Checksum check

  • Check that the reference checksum in the file SHA256SUMS matches the checksum calculated by you
grep bitcoin-$VERSION.tar.gz SHA256SUMS | sha256sum -c
output
bitcoin-$VERSION.tar.gz: OK

Signature check

Bitcoin releases are signed by several individuals, each using its own key. To verify the validity of these signatures, you must first import the corresponding public keys into your GPG key database.

  • Install gnupg
$SU apk add gnupg
wget -qO- \
    "https://api.github.com/repositories/355107265/contents/builder-keys" |\
    grep download_url |\
    grep -oE "https://[a-zA-Z0-9./-]+" |\
    while read url; do \
        wget -qO- "$url" |\
        gpg --import \
    ; done
  • Verify that the checksums file is cryptographically signed by the release signing keys. The following command prints signature checks for each of the public keys that signed the checksums
gpg --verify SHA256SUMS.asc
  • Check that at least a few signatures show the following text
output
gpg: Good signature from...
Primary key fingerprint:...

Extract source

If you're satisfied with the checksum, and signature, extract the Bitcoin Knots source code

tar xzf bitcoin-$VERSION.tar.gz && cd bitcoin-$VERSION

Install dependencies

These are make dependencies (safe to remove after installation, if you want)

$SU apk add autoconf automake boost-dev clang chrpath file libevent-dev libtool make pkgconf zeromq-dev

These are runtime dependencies

$SU apk add libevent libsodium libstdc++ libzmq

Apply patches

sed '/#include <string>/a #include <cstdint>' src/node/mempool_args.h > _
mv -f _ src/node/mempool_args.h
sed 's/C.UTF-8/C/' src/common/system.cpp > _
mv -f _ src/common/system.cpp

Configure, compile and install

For convenience, it might be useful to have the manual page for bitcoin-cli in the same machine so that they can be consulted offline, it's installed by default in this guide

If you DON'T want it, execute this

MAN=--disable-man
./autogen.sh
./configure \
    --prefix=/usr \
    "${MAN:---mandir=/usr/share/man}" \
    --with-daemon \
    --with-utils \
    --without-bdb \
    --without-gui \
    --without-libs \
    --without-qrencode \
    --enable-hardening \
    --enable-lto \
    --enable-reduce-exports \
    --enable-static \
    --disable-bench \
    --disable-ccache \
    --disable-fuzz \
    --disable-fuzz-binary \
    --disable-gui-tests \
    --disable-maintainer-mode \
    --disable-shared \
    --disable-tests \
    --disable-wallet
make
$SU make install
[ -z $MAN ] && $SU apk add mandoc man-pages
$SU install -D -m 0660 -o bitcoin -g bitcoin ./share/examples/bitcoin.conf /etc/bitcoin/bitcoin.conf

Strip installed binaries

$SU strip -v /usr/bin/bitcoin*

Generate access credentials

For other programs to query Bitcoin Knots they need the proper access credentials. To avoid storing the username and password in a configuration file in plaintext, the password is hashed. This allows Bitcoin Knots to accept a password, hash it, and compare it to the stored hash, while it is not possible to retrieve the original password.

Another option to get access credentials is through the .cookie file in the Bitcoin data directory. This is created automatically and can be read by all users who are members of the "bitcoin" group.

Bitcoin Knots provides a simple python script to generate the configuration line for the config file.

But we prefer to do it our way, much more simple

read -r username password; \
[ ! "$username" ] || [ ! "$password" ] && { 
    printf "%s\n" "Error, must provide username and password"
} || {
    sed "s/^#*rpcauth=.*$/rpcauth=${username}:${salt=$(openssl rand -hex 16)}\$$(\
            printf "%s" "${password}" | \
            openssl dgst -sha256 -hmac "$salt" | \
            awk '{print $2}' \
        )/" /etc/bitcoin/bitcoin.conf > _; \
    unset salt; \
    $SU mv -f _ /etc/bitcoin/bitcoin.conf
}

Configuration

⚠️

"dbcache=..." need to be adjusted to your hardware capacity

  • Modify/uncomment these lines. Save and exit.
$SU $EDITOR /etc/bitcoin/bitcoin.conf
/etc/bitcoin/bitcoin.conf
[...]
assumevalid=0
[...]
blockfilterindex=1
[...]
blocksonly=1
[...]
coinstatsindex=1
[...]
dbcache=8192
[...]
txindex=1
[...]
i2psam=127.0.0.1:7656
[...]
onion=127.0.0.1:9050
[...]
peerblockfilters=1
[...]
peerbloomfilters=1
[...]
zmqpubhashblock=tcp://127.0.0.1:8433
[...]
zmqpubrawblock=tcp://127.0.0.1:28332
[...]
zmqpubrawtx=tcp://127.0.0.1:28333
[...]
debug=i2p
debug=tor
[...]
server=1
[...]
💡

Check this Bitcoin Knots sample config (opens in a new tab) on web browser

Reject non-private networks
/etc/bitcoin/bitcoin.conf
[...]
onlynet=onion
[...]
onlynet=i2p
[...]
dns=0
[...]
dnsseed=0
[...]

And add seed nodes, check a list of seed nodes here (opens in a new tab)

/etc/bitcoin/bitcoin.conf
##Tor seed nodes
seednode=2bqghnldu6mcug...tvci6klcwzepnjd46ikjyd.onion:8333
[...]
##I2P seed nodes
seednode=255fhcp6ajvftn...3bamyh2iu5r3gnr2rq.b32.i2p:0
[...]
Slow device mode
/etc/bitcoin/bitcoin.conf
[...]
# Slow devices optimizations
## Limit the number of max peers connections
maxconnections=40
[...]
## Tries to keep outbound traffic under the given target per 24h
maxuploadtarget=5000
[...]
## Increase the number of threads to service RPC calls (default: 4)
rpcthreads=128
[...]
## Increase the depth of the work queue to service RPC calls (default: 16)
rpcworkqueue=256
[...]
#coinstatsindex=1
[...]
#assumevalid=0
[...]
💡

Realize that with maxuploadtarget parameter enabled you will need whitelist the connection to Electrs and Bisq by adding these parameter to bitcoin.conf:

  • Electrs: whitelist=download@127.0.0.1
  • Bisq: whitelist=bloomfilter@192.168.0.0/16

Create init.d service

The system needs to run the bitcoin daemon automatically in the background, even when nobody is logged in. We use openrc, a daemon that controls the startup process using configuration files.

  • Create the init.d configuration
$SU $EDITOR /etc/init.d/bitcoind
  • Enter the complete next configuration. Save and exit
/etc/init.d/bitcoind
#!/sbin/openrc-run
 
: ${BITCOIND_CONFIGFILE:=/etc/bitcoin/bitcoin.conf}
: ${BITCOIND_DATADIR:=/var/lib/bitcoind}
: ${BITCOIND_LOGDIR:=/var/log/bitcoind}
: ${BITCOIND_USER:=bitcoin}
: ${BITCOIND_GROUP:=bitcoin}
: ${BITCOIND_BIN:=/usr/bin/bitcoind}
: ${BITCOIND_OPTS=${BITCOIN_OPTS}}
: ${BITCOIND_SIGTERM_TIMEOUT:=600}
 
name="Bitcoin Knots daemon"
description="Bitcoin cryptocurrency P2P network daemon"
 
required_files="${BITCOIND_CONFIGFILE}"
pidfile="/run/${SVCNAME}.pid"
retry="${BITCOIND_SIGTERM_TIMEOUT}"
 
command="${BITCOIND_BIN}"
command_args="-pid=${pidfile}
              -conf=${BITCOIND_CONFIGFILE}
              -datadir=${BITCOIND_DATADIR}
              -debuglogfile=${BITCOIND_LOGDIR}/debug.log
              ${BITCOIND_OPTS}"
command_args_background="-daemonwait"
command_user="${BITCOIND_USER}:${BITCOIND_GROUP}"
 
depend() {
    use net
    need localmount
    checkdepend onion tor
    checkdepend i2psam i2pd
    after logger firewall
}
 
checkdepend() {
    if grep -qs "^${1}=" "${BITCOIND_CONFIGFILE}"; then
        need "${2:-$1}"
    fi
}
 
start_pre() {
    checkpath --file      --mode 0660 --owner "${command_user}" "${BITCOIND_CONFIGFILE}"
    checkpath --directory --mode 0750 --owner "${command_user}" "${BITCOIND_DATADIR}"
    checkpath --directory --mode 0755 --owner "${command_user}" "${BITCOIND_LOGDIR}"
    checkconfig
}
 
start_post() {
    chmod -R u=rwX,g=rX,o= "${BITCOIND_DATADIR}" "${BITCOIND_LOGDIR}"
}
 
checkconfig() {
    if ! grep -qs '^rpcauth=' "${BITCOIND_CONFIGFILE}"
    then
        eerror ""
        eerror "ERROR: You must set a secure rpcauth to run bitcoind."
        eerror "The setting must appear in ${BITCOIND_CONFIGFILE}"
        eerror ""
        eerror "This auth is security critical to securing wallets "
        eerror "and must not be the same as the rpcuser setting."
        eerror ""
        eerror "It is recommended that you also set alertnotify so you are "
        eerror "notified of problems:"
        eerror ""
        eerror "ie: alertnotify=echo %%s | mail -s \"Bitcoin Alert\"" \
            "admin@foo.com"
        eerror ""
        return 1
    fi
}
  • Enable execution permission
$SU chmod +x /etc/init.d/bitcoind
  • Enable autoboot
$SU rc-update add bitcoind default

Create logrotate config

Logrotate is a system utility that manages the compression and rotation of log files on Linux systems. If logs are not rotated, compressed, and purged periodically, they can eventually consume all available disk space on the system. It allows automatic rotation, compression, removal, and mailing of log files. Each log file may be handled daily, weekly, monthly, or when it grows too large.

Normally, logrotate is run as a daily cron job.

  • Create the bitcoin logrotate config file
$SU $EDITOR /etc/logrotate.d/bitcoind
  • Enter the complete next configuration. Save and exit
/etc/logrotate.d/bitcoind
/var/log/bitcoind/*.log {
    weekly
    missingok
    rotate 104
    compress
    delaycompress
    notifempty
    create 0640 bitcoin bitcoin
    sharedscripts
    postrotate
        killall -HUP `cat /run/bitcoind.pid`
    endscript
}
  • Test
$SU logrotate /etc/logrotate.d/bitcoind --debug

Run

  • Start the service
$SU rc-service bitcoind start
  • Check logs
tail -f /var/log/bitcoind/debug.log
output
2024-01-17T13:48:34Z Bitcoin Core version v26.0.0 (release build)
2024-01-17T13:48:34Z InitParameterInteraction: parameter interaction: -blocksonly=1 -> setting -whitelistrelay=0
2024-01-17T13:48:34Z InitParameterInteraction: parameter interaction: -blocksonly=1 -> setting -maxmempool=5
2024-01-17T13:48:34Z Using the 'sse4(1way),sse41(4way),avx2(8way)' SHA256 implementation
2024-01-17T13:48:34Z Using RdSeed as an additional entropy source
2024-01-17T13:48:34Z Using RdRand as an additional entropy source
2024-01-17T13:48:34Z Default data directory /dev/null/.bitcoin
2024-01-17T13:48:34Z Using data directory /var/lib/bitcoind
2024-01-17T13:48:34Z Config file: /etc/bitcoin/bitcoin.conf
2024-01-17T13:48:34Z Config file arg: assumevalid="0"
2024-01-17T13:48:34Z Config file arg: blockfilterindex="1"
2024-01-17T13:48:34Z Config file arg: blocksonly="1"
2024-01-17T13:48:34Z Config file arg: coinstatsindex="1"
2024-01-17T13:48:34Z Config file arg: daemon="1"
2024-01-17T13:48:34Z Config file arg: dbcache="24576"
2024-01-17T13:48:34Z Config file arg: debug="i2p"
2024-01-17T13:48:34Z Config file arg: debug="tor"
2024-01-17T13:48:34Z Config file arg: debuglogfile="/var/log/bitcoind/debug.log"
2024-01-17T13:48:34Z Config file arg: i2psam="127.0.0.1:7656"
2024-01-17T13:48:34Z Config file arg: onion="127.0.0.1:9050"
2024-01-17T13:48:34Z Config file arg: peerblockfilters="1"
2024-01-17T13:48:34Z Config file arg: peerbloomfilters="1"
2024-01-17T13:48:34Z Config file arg: rpcauth=****
2024-01-17T13:48:34Z Config file arg: server="1"
2024-01-17T13:48:34Z Config file arg: startupnotify="chmod -R u=rwX,g=rX,o= /var/lib/bitcoind /var/log/bitcoind"
2024-01-17T13:48:34Z Config file arg: txindex="1"
2024-01-17T13:48:34Z Config file arg: v2transport="1"
2024-01-17T13:48:34Z Command-line arg: conf="/etc/bitcoin/bitcoin.conf"
2024-01-17T13:48:34Z Command-line arg: datadir="/var/lib/bitcoind"
2024-01-17T13:48:34Z Command-line arg: pid="/run/bitcoind/bitcoin.pid"
2024-01-17T13:48:34Z Command-line arg: server=""
[...]
2024-01-17T13:48:46Z Pre-synchronizing blockheaders, height: 2000 (~0.25%)
[...]

Monitor the log file for a few minutes to see if it works fine (it may stop at dnsseed thread exit, that's ok)

  • Wait a few minutes until Bitcoin Core starts, and enter the next command to obtain your Tor and I2P addresses. Take note of them, later you might need it
bitcoin-cli getnetworkinfo | grep 'address.*\.onion\|address.*\.i2p'
output
"address": "vctk9tie5srguvz262xpyukkd7g4z2xxxy5xx5ccyg4f12fzop8hoiad.onion",
"address": "sesehks6xyh31nyjldpyeckk3ttpanivqhrzhsoracwqjxtk3apgq.b32.i2p",
  • Check the correct enablement of the I2P and Tor networks
bitcoin-cli -netinfo
output
Bitcoin Core client v26.0.0 - server 70016/Satoshi:26.0.0/
          ipv4    ipv6   onion   i2p   total   block
in          0       0      25     2      27
out         7       0       2     1      10       2
total       7       0      27     3      37
 
Local addresses
xdtk6tie4srguvz566xpyukkd7m3z3vbby5xx5ccyg5f64fzop7hoiab.onion     port   8333    score      4
etehks3xyh55nyjldjdeckk3nwpanivqhrzhsoracwqjxtk8apgk.b32.i2p       port      0    score      4
  • Ensure bitcoind is listening on the default RPC & P2P ports
$SU netstat -lntup | grep LISTEN | grep bitcoind
output
tcp        0      0 0.0.0.0:8333            0.0.0.0:*               LISTEN      28295/bitcoind
tcp        0      0 127.0.0.1:8334          0.0.0.0:*               LISTEN      28295/bitcoind
tcp        0      0 127.0.0.1:8332          0.0.0.0:*               LISTEN      28295/bitcoind
tcp        0      0 127.0.0.1:8433          0.0.0.0:*               LISTEN      28295/bitcoind
tcp        0      0 127.0.0.1:28332         0.0.0.0:*               LISTEN      28295/bitcoind
tcp        0      0 127.0.0.1:28333         0.0.0.0:*               LISTEN      28295/bitcoind
tcp        0      0 :::8333                 :::*                    LISTEN      28295/bitcoind
tcp        0      0 ::1:8332                :::*                    LISTEN      28295/bitcoind

Please note:

  • When bitcoind is still starting, you may get an error message like “verifying blocks”. That’s normal, just give it a few minutes.

  • Among other info, the “verificationprogress” is shown. Once this value reaches almost 1 (0.99999…), the blockchain is up-to-date and fully validated.

Bitcoin Knots is syncing

This can take between one day and a week, depending mostly on your PC performance. It's best to wait until the synchronization is complete before going ahead.

Explore bitcoin-cli

If everything is running smoothly, this is the perfect time to familiarize yourself with Bitcoin, the technical aspects of Bitcoin Core, and play around with bitcoin-cli until the blockchain is up-to-date.

Activate mempool & reduce 'dbcache' after a full sync

Once Bitcoin Knots is fully synced, we can reduce the size of the database cache. A bigger cache speeds up the initial block download, now we want to reduce memory consumption to allow the Lightning client and Electrum server to run in parallel. We also now want to enable the node to listen to and relay transactions.

  • Comment the following lines on bitcoin.conf file
💡

Bitcoin Knots will then just use the default cache size of 450 MiB instead of your setting RAM setup. If blocksonly=1 is left uncommented it will prevent Electrum Server from receiving RPC fee data and will not work.

$SU $EDITOR /etc/bitcoin/bitcoin.conf
/etc/bitcoin/bitcoin.conf
#dbcache=2048
#blocksonly=1
#assumevalid=0
  • Restart Bitcoin Knots for the settings to take effect
$SU rc-service bitcoind restart

Upgrade

The latest release can be found on the GitHub page (opens in a new tab) of the Bitcoin Knots project. Always read the RELEASE NOTES (opens in a new tab) first! When upgrading, there might be breaking changes or changes in the data structure that need special attention. Replace the environment variable VERSION=x.xx value for the latest version if it has not been already changed in this guide.