Bitcoin Core - tulliolo/mobybolt GitHub Wiki
We install Bitcoin Core, the reference client implementation of the Bitcoin network. If you prefer to use Bitcoin Knots, please refer to this guide.
â You can't install Bitcoin and Knots and Bitcoin Core together.
â To follow this section, log in to your node as admin user via Secure Shell (SSH) and access the project's home:
$ cd apps/mobybolt
Bitcoin Core will download the full Bitcoin blockchain, and validate all transactions since 2009. We're talking more than 800000 blocks with a size of over 465 GB, so this is not an easy task.
Create the directories:
$ mkdir -p bitcoin-core/patches
Edit the .env file and append the following content to the end:
$ nano .env
# bitcoin
BITCOIN_VERSION=28.0
BITCOIN_ADDRESS=172.16.21.4
BITCOIN_GID=1100
BITCOIN_UID=1100
đĄ In this file:
- we define the
BITCOIN_VERSION(check the latest available version here); - we define a static address for the container;
- we define the
uid(user id) andgid(group id) of the bitcoin user.
Create the Dockerfile and populate it with the following content:
$ nano bitcoin-core/Dockerfile
# base image
FROM debian:stable-slim AS base
# install dependencies
RUN set -eux && \
apt update && \
apt install -y \
# build requirements
automake \
autotools-dev \
bsdmainutils \
build-essential \
ccache \
curl \
git \
libtool \
pkg-config \
python3 \
# dependencies
libboost-dev \
libevent-dev \
libsqlite3-dev \
libzmq3-dev && \
rm -rf /var/lib/apt/lists/*
# builder image
FROM base AS builder
ARG BITCOIN_VERSION
ENV BITCOIN_URL="https://github.com/bitcoin/bitcoin.git" \
BITCOIN_KEYS_URL="https://api.github.com/repositories/355107265/contents/builder-keys"
RUN set -eux && \
# clone repository
git clone --branch "v$BITCOIN_VERSION" $BITCOIN_URL && \
# imports automatically all signatures from the Bitcoin Core release attestations (Guix) repository
curl -s \
$BITCOIN_KEYS_URL |\
grep download_url |\
grep -oE "https://[a-zA-Z0-9./-]+" |\
while read url; do \
curl -s "$url" |\
gpg --import; \
done
# copy patches
COPY patches/ /patches/
WORKDIR bitcoin
RUN set -xe && \
# verify signature
git verify-tag "v$BITCOIN_VERSION" && \
# build bdb 4.8
make -C depends NO_BOOST=1 NO_LIBEVENT=1 NO_QT=1 NO_SQLITE=1 NO_NATPMP=1 NO_UPNP=1 NO_ZMQ=1 NO_USDT=1 && \
# apply patches
for patch in $( find /patches -type f ); do \
git apply $patch; \
done && \
# configure
./autogen.sh && \
export BDB_PREFIX="$PWD/depends/$( ls depends | grep linux-gnu )" && \
./configure \
BDB_LIBS="-L${BDB_PREFIX}/lib -ldb_cxx-4.8" BDB_CFLAGS="-I${BDB_PREFIX}/include" \
--disable-bench \
--disable-gui-tests \
--disable-maintainer-mode \
--disable-man \
--disable-tests \
--with-daemon=yes \
--with-gui=no \
--with-qrencode=no \
--with-utils=yes && \
# build
make -j$(nproc) && \
# install
make install
# base image
FROM debian:stable-slim
# copy bitcoin binaries and libraries
COPY --from=builder /usr/local/bin/ /usr/local/bin/
COPY --from=builder /usr/local/lib/ /usr/local/lib/
# install dependencies
RUN set -eux && \
apt update && \
apt install -y \
libevent-dev \
libsqlite3-dev \
libzmq3-dev && \
rm -rf /var/lib/apt/lists/*
# default uid for bitcoin user
ARG BITCOIN_GID=1100
ARG BITCOIN_UID=1100
# default gid for tor group
ARG TOR_GID=102
# setup bitcoin user
RUN set -eux && \
addgroup --gid $BITCOIN_GID bitcoin && \
adduser --disabled-password --comment "" --gid $BITCOIN_GID --uid $BITCOIN_UID bitcoin && \
addgroup --gid $TOR_GID tor && \
adduser bitcoin tor
# setup dirs and permissions
RUN set -eux && \
mkdir -m 0750 /home/bitcoin/.bitcoin && \
mkdir -m 0700 /run/bitcoind && \
chown bitcoin /run/bitcoind && \
chown bitcoin:bitcoin /home/bitcoin/.bitcoin /run/bitcoind
# setup entrypoint
COPY --chmod=0755 ./docker-entrypoint.sh /usr/local/bin/
ENTRYPOINT ["docker-entrypoint.sh"]
# switch user
USER bitcoin
đĄ In this file:
- we define a builder image (
builder) to buid bitcoin from github sources, verifying version tag signatures; - we define a result image:
- installing the needed dependencies;
- copying libraries and binaries from the builder image;
- configuring the
bitcoinuser and the directories to which he will have access; - setting the
entrypoint(the script to run when the container starts).
Create the entrypoint file and populate it with the following content:
$ nano bitcoin-core/docker-entrypoint.sh
#!/bin/bash
set -eo pipefail
function die_func() {
echo "INFO: got SIGTERM... exiting"
exit 1
}
trap die_func TERM
function wait_for_config () {
echo "WARNING: missing configuration file"
while ! [[ -f $CONF_FILE ]]; do
echo "--> waiting for $CONF_FILE"
sleep 30
done
echo "INFO: found configuration file!"
}
CMD=$@
DATA_DIR=/home/bitcoin/.bitcoin
CONF_FILE="$DATA_DIR/bitcoin.conf"
PID_FILE=/run/bitcoind/bitcoind.pid
if [[ $# -eq 0 ]]; then
# missing parameters, run bitcoind
CMD="bitcoind -conf=$CONF_FILE -datadir=$DATA_DIR -pid=$PID_FILE"
if ! [[ -f $CONF_FILE ]]; then
wait_for_config
fi
fi
exec $CMD
đĄ In this file:
- we define the default files and directories;
- we wait for a configuration file;
- we run bitcoin.
Ordinals is a project created to number sats. It also has a feature called inscriptions, which is the problematic part and what is mainly being touched on in this guide. An inscription is basically data stored onchain associated with a sat.
Ordisrespector is a spam patch filter that works by detecting the pattern of Ordinals transactions that are entering the mempool of the node and rejecting them. The original patch was created by Luke Dashjr, you can see it here.
In order to apply the spam filter, simply download the Ordisrespector patch and put it in the pathes dir. The next Bitcoin Core build will apply it:
$ wget -P bitcoin-core/patches/ https://raw.githubusercontent.com/minibolt-guide/minibolt/main/resources/ordisrespector.patch
Carefully check the downloaded patch:
$ cat bitcoin-core/patches/ordisrespector.patch
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index 03b157a84..e7d9e96d0 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -479,6 +479,14 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
return set_error(serror, SCRIPT_ERR_MINIMALDATA);
}
stack.push_back(vchPushValue);
+ if ((flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) && opcode == OP_FALSE) {
+ auto pc_tmp = pc;
+ opcodetype next_opcode;
+ valtype dummy_data;
+ if (script.GetOp(pc_tmp, next_opcode, dummy_data) && next_opcode == OP_IF) {
+ return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
+ }
+ }
} else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF))
switch (opcode)
{
Create the bitcoin configuration file and populate it with the following content:
$ nano bitcoin-core/bitcoin.conf
# MobyBolt: bitcoind configuration
# /home/bitcoin/.bitcoin/bitcoin.conf
## Bitcoin daemon
server=1
txindex=1
# Additional logs
debug=tor
debug=i2p
# Assign read permission to the Bitcoin group users
startupnotify=chmod g+r /home/bitcoin/.bitcoin/.cookie
# Disable debug.log
nodebuglogfile=1
# Avoid assuming that a block and its ancestors are valid,
# and potentially skipping their script verification.
# We will set it to 0, to verify all.
assumevalid=0
# Enable all compact filters
blockfilterindex=1
# Support filtering of blocks and transactions with bloom filters
peerbloomfilters=1
# Serve compact block filters to peers per BIP 157
peerblockfilters=1
# Maintain coinstats index used by the gettxoutsetinfo RPC
coinstatsindex=1
# Network
bind=172.16.21.4:8333
bind=172.16.21.4:8334=onion
listen=1
# Connect to clearnet using Tor SOCKS5 proxy
proxy=172.16.21.2:9050
onion=172.16.21.2:9050
# Tor control <ip:port> to use if onion listening enabled.
torcontrol=172.16.21.2:9051
# I2P SAM proxy to reach I2P peers and accept I2P connections
i2psam=172.16.21.3:7656
# RPC
rpcbind=0.0.0.0
rpcallowip=172.16.21.0/24
# ZMQ
zmqpubhashblock=tcp://0.0.0.0:8433
# Initial block download optimizations (set dbcache size in megabytes
# (4 to 16384, default: 300) according to the available RAM of your device,
# recommended: dbcache=1/2 x RAM available e.g: 4GB RAM -> dbcache=2048)
# Remember to comment after IBD!
dbcache=4096
blocksonly=1
dbcache=... need to be adjusted to your hardware capacity
Add these lines to the end of the file, remember to add seed nodes. You can add more seed nodes to this list: seed nodes. Save and exit.
# Reject non-private networks
onlynet=onion
onlynet=i2p
dns=0
dnsseed=0
##Tor seed nodes
seednode=2bqghnldu6mcug4pikzprwhtjjnsyederctvci6klcwzepnjd46ikjyd.onion:8333
seednode=4lr3w2iyyl5u5l6tosizclykf5v3smqroqdn2i4h3kq6pfbbjb2xytad.onion:8333
seednode=5g72ppm3krkorsfopcm2bi7wlv4ohhs4u4mlseymasn7g7zhdcyjpfid.onion:8333
seednode=5sbmcl4m5api5tqafi4gcckrn3y52sz5mskxf3t6iw4bp7erwiptrgqd.onion:8333
seednode=776aegl7tfhg6oiqqy76jnwrwbvcytsx2qegcgh2mjqujll4376ohlid.onion:8333
seednode=77mdte42srl42shdh2mhtjr7nf7dmedqrw6bkcdekhdvmnld6ojyyiad.onion:8333
seednode=azbpsh4arqlm6442wfimy7qr65bmha2zhgjg7wbaji6vvaug53hur2qd.onion:8333
seednode=b64xcbleqmwgq2u46bh4hegnlrzzvxntyzbmucn3zt7cssm7y4ubv3id.onion:8333
seednode=bsqbtcparrfihlwolt4xgjbf4cgqckvrvsfyvy6vhiqrnh4w6ghixoid.onion:8333
seednode=bsqbtctulf2g4jtjsdfgl2ed7qs6zz5wqx27qnyiik7laockryvszqqd.onion:8333
##I2P seed nodes
seednode=255fhcp6ajvftnyo7bwz3an3t4a4brhopm3bamyh2iu5r3gnr2rq.b32.i2p:0
seednode=27yrtht5b5bzom2w5ajb27najuqvuydtzb7bavlak25wkufec5mq.b32.i2p:0
seednode=3gocb7wc4zvbmmebktet7gujccuux4ifk3kqilnxnj5wpdpqx2hq.b32.i2p:0
seednode=4fcc23wt3hyjk3csfzcdyjz5pcwg5dzhdqgma6bch2qyiakcbboa.b32.i2p:0
seednode=4osyqeknhx5qf3a73jeimexwclmt42cju6xdp7icja4ixxguu2hq.b32.i2p:0
seednode=4umsi4nlmgyp4rckosg4vegd2ysljvid47zu7pqsollkaszcbpqq.b32.i2p:0
seednode=6j2ezegd3e2e2x3o3pox335f5vxfthrrigkdrbgfbdjchm5h4awa.b32.i2p:0
seednode=6n36ljyr55szci5ygidmxqer64qr24f4qmnymnbvgehz7qinxnla.b32.i2p:0
seednode=72yjs6mvlby3ky6mgpvvlemmwq5pfcznrzd34jkhclgrishqdxva.b32.i2p:0
seednode=a5qsnv3maw77mlmmzlcglu6twje6ttctd3fhpbfwcbpmewx6fczq.b32.i2p:0
seednode=aovep2pco7v2k4rheofrgytbgk23eg22dczpsjqgqtxcqqvmxk6a.b32.i2p:0
seednode=bitcoi656nll5hu6u7ddzrmzysdtwtnzcnrjd4rfdqbeey7dmn5a.b32.i2p:0
seednode=brifkruhlkgrj65hffybrjrjqcgdgqs2r7siizb5b2232nruik3a.b32.i2p:0
seednode=c4gfnttsuwqomiygupdqqqyy5y5emnk5c73hrfvatri67prd7vyq.b32.i2p:0
seednode=day3hgxyrtwjslt54sikevbhxxs4qzo7d6vi72ipmscqtq3qmijq.b32.i2p:0
seednode=du5kydummi23bjfp6bd7owsvrijgt7zhvxmz5h5f5spcioeoetwq.b32.i2p:0
seednode=e55k6wu46rzp4pg5pk5npgbr3zz45bc3ihtzu2xcye5vwnzdy7pq.b32.i2p:0
seednode=eciohu5nq7vsvwjjc52epskuk75d24iccgzmhbzrwonw6lx4gdva.b32.i2p:0
Create the Docker Compose file and populate it with the following content:
$ nano bitcoin-core/docker-compose.yml
services:
bitcoin:
build:
context: .
args:
BITCOIN_VERSION: ${BITCOIN_VERSION}
BITCOIN_GID: ${BITCOIN_GID}
BITCOIN_UID: ${BITCOIN_UID}
TOR_GID: ${TOR_GID}
container_name: ${COMPOSE_PROJECT_NAME}_bitcoin
expose:
- "8332"
- "8334"
healthcheck:
test: ["CMD-SHELL", "bitcoin-cli getconnectioncount | sed 's/^[1-9][0-9]*$/OK/' | grep OK || exit 1"]
interval: 1m
timeout: 10s
retries: 3
start_period: 5m
image: ${COMPOSE_PROJECT_NAME}/bitcoin:${BITCOIN_VERSION}
networks:
default:
ipv4_address: ${BITCOIN_ADDRESS}
restart: unless-stopped
stop_grace_period: 5m
volumes:
- bitcoin-data:/home/bitcoin/.bitcoin/
- ./bitcoin.conf:/home/bitcoin/.bitcoin/bitcoin.conf:ro
- tor-data:/var/lib/tor/:ro
volumes:
bitcoin-data:
đĄ In this file:
- we
buildthe Dockerfile and create an image namedmobybolt/bitcoin:<version>; - we define a
healthcheckthat will check every minute that the bitcoin client is connected to at least one peer; - we define the
restartpolicy of the container in case of failures; - we provide the container with the
BITCOIN_ADDRESSstatic address; - we provide the container with the previously defined configuration (bind mount) and with a volume named
mobybolt_bitcoin-datato store persistent data.
Edit the main Docker Compose file and link the bitcoin docker compose file in the include section:
$ nano docker-compose.yml
The file should look like this:
include:
- ...
- bitcoin-core/docker-compose.ymlRun the following command and check the output:
$ docker compose config --quiet && printf "OK\n" || printf "ERROR\n"
> OK
đĄ If the output is not OK, check the error reported... Maybe some wrong indentation in the yaml files?
Let's build the bitcoin image by typing:
$ docker compose build bitcoin
Check for a new image called mobybolt/bitcoin:<version>:
$ docker images | grep bitcoin
> mobybolt/bitcoin 28.0 30adc7959c8e About a minute ago 795MB
Run the following command and check the output:
$ docker compose up -d bitcoin
> [+] Running 2/2
> â Volume "mobybolt_bitcoin-data" Created
> â Container mobybolt_bitcoin Started
Check the container logs:
$ docker logs mobybolt_bitcoin
> 2024-05-25T11:55:44Z Bitcoin Core version v27.1 (release build)
> ...
> 2024-05-25T11:55:44Z Default data directory /home/bitcoin/.bitcoin
> 2024-05-25T11:55:44Z Using data directory /home/bitcoin/.bitcoin
> 2024-05-25T11:55:44Z Config file: /home/bitcoin/.bitcoin/bitcoin.conf
> ...
> 2024-05-25T11:55:44Z [tor] Successfully connected!
> 2024-05-25T11:55:44Z [tor] Connected to Tor version 0.4.8.11
> 2024-05-25T11:55:44Z [tor] Supported authentication method: COOKIE
> 2024-05-25T11:55:44Z [tor] Supported authentication method: SAFECOOKIE
> 2024-05-25T11:55:44Z [tor] Using SAFECOOKIE authentication, reading cookie authentication from /var/lib/tor/control_auth_cookie
> ...
> 2024-05-25T11:55:44Z [tor] Authentication successful
Check the container status:
$ docker ps | grep bitcoin
> 5bd04a4dbc34 mobybolt/bitcoin:28.0 "docker-entrypoint.sh" About a minute ago Up About a minute (health: starting) 8332/tcp, 8334/tcp mobybolt_bitcoin
(healthy), or (health: starting). Any other status is incorrect.
đĄ If the container is in (health: starting) state, wait a few minutes and repeat the above command until the state changes to (healthy). If this does not happen, the run has failed.
âšī¸ If not already present, docker will also create the mobybolt_tor-data volume. You can check for it with the command:
$ docker volume ls | grep bitcoin
> local mobybolt_bitcoin-data
Run the following command:
$ docker exec mobybolt_bitcoin bitcoin-cli -getinfo
> Chain: main
> Blocks: 844910
> Headers: 844910
> Verification progress: 100.0000%
> ...
Bitcoin Core will be fully syncronized when the verification progress reaches 100% (or 99.xxx%).
Run the following command:
$ docker exec mobybolt_bitcoin bitcoin-cli -netinfo
> ...
> onion i2p total block
> in 0 2 2
> out 2 8 10 2
> total 2 10 12
>
> Local addresses
> abcdef.onion port 8333 score 4
> abcdef.b32.i2p port 0 score 4
You should see some out connections and your onion/i2p local addresses.
This can take between one day and a week, depending mostly on your PC and network performance. It's best to wait until the synchronization is complete before going ahead.
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.
- The Little Bitcoin Book is a fantastic introduction to Bitcoin, focusing on the "why" and less on the "how"
- Mastering Bitcoin by Andreas Antonopoulos is a great point to start, especially chapter 3:
- Learning Bitcoin from the Command Line by Christopher Allen gives a thorough deep dive into understanding the technical aspects of Bitcoin
- Also, check out the bitcoin-cli reference
Once Bitcoin Core is fully synched, 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.
Edit the bitcoin configuration file and comment (prepending a #) the following lines:
$ nano bitcoin-core/bitcoin.conf
#dbcache=2048
#blocksonly=1
#assumevalid=0Restart Bitcoin Core:
$ docker compose restart bitcoin
> [+] Restarting 1/1
> â Container mobybolt_bitcoin Started
Check the Bitcoin Core release page for a new version and change the BITCOIN_VERSION value in the .env file.
Then, redo the steps described in:
If everything is ok, you can clear the old image and build cache, like in the following example:
$ docker image ls | grep bitcoin
> mobybolt/bitcoin 28.0 30adc7959c8e 46 minutes ago 795MB
> mobybolt/bitcoin 27.1 56f39c90e8ac 4 weeks ago 795MB
$ docker image rm mobybolt/bitcoin:27.1
> Untagged: mobybolt/bitcoin:27.1
> Deleted: sha256:56f39c90e8accbfae77a3c8ed9e6e5794d67c62d1944c2c0ce4c7bc3dd233f07
$ docker buildx prune
> WARNING! This will remove all dangling build cache. Are you sure you want to continue? [y/N] y
> ID RECLAIMABLE SIZE LAST ACCESSED
> nd48am5z5nzmiiule5r8b1t8q* true 0B About an hour ago
> ...
> Total: 5.711GB
Follow the next steps to uninstall bitcoin:
-
Remove the container:
$ docker compose down bitcoin > [+] Running 2/1 > â Container mobybolt_bitcoin Removed > ... -
Remove the image:
$ docker image rm $(docker images | grep bitcoin | awk '{print $3}') > Untagged: mobybolt/bitcoin:28.0 > Deleted: sha256:13afebf08e29c6b9a526a6e54ab1f93e745b25080add4e37af8f08bdf6cfbcc6 -
Clean the build cache:
$ docker buildx prune > WARNING! This will remove all dangling build cache. Are you sure you want to continue? [y/N] y > ID RECLAIMABLE SIZE LAST ACCESSED > 7r8ccrpq0g0e03deu2dh53ob6* true 9.69MB 19 minutes ago > ndrhcdo756vejnx17qm775t08* true 1.212kB 24 minutes ago > ... -
Remove the volume (optional):
â ī¸ you will lose all the synchronized blocks dataâ ī¸ $ docker volume rm mobybolt_bitcoin-data > mobybolt_bitcoin-data -
Remove files and directories (optional):
$ rm -rf bitcoin-core