joininbox/scripts/standalone/_functions.standalone.sh
openoms 16fc83f47d
Some checks are pending
amd64-image-build / amd64-image-build (push) Waiting to run
arm64-rpi-image-build / arm64-rpi-image-build (push) Waiting to run
Test Shellcheck / Run Shellcheck (push) Waiting to run
chore: migrate the watch-only Bitcoin Core wallet to use descriptors (#177)
* chore: update wallet creation to use watch-only-descriptor-wallet

* remove duplicate version check

* fix: update release URL in install script and correct typo in wallet import message

* ci: test amd64 image descriptor wallet migration with Bats

* ci: boot amd64 image tests with OVMF pflash

* fix: gate descriptor wallet migration on Bitcoin Core v30

Detect the connected Bitcoin Core version over RPC before migrating.
Keep wallet.dat for v29.x or when the version cannot be determined.

Add regression coverage for both migration and compatibility paths.

* ci: make amd64 image tests independent of guest apt

Inject a pinned bats-core checkout into the temporary VM instead of
installing Bats through the guest package repositories.

Remove the duplicate pull request trigger and simplify artifact lookup.

* ci: harden image build run

* docs(FAQ): how automatic migration works
2026-08-13 11:57:42 +02:00

298 lines
10 KiB
Bash
Executable file

#!/bin/bash
function addUserStore() {
if [ ! -d /home/store/app-data ]; then
echo "# Adding the user: store"
sudo adduser --system --group --home /home/store store
sudo -u store mkdir /home/store/app-data
echo "# Add the joinmarket user to the store group"
sudo usermod -aG store joinmarket
else
echo "# The folder /home/store/app-data is present already"
fi
}
function moveSignetData() {
if [ -f /etc/systemd/system/signetd.service ]; then
sudo systemctl stop signetd
sudo mv /home/joinmarket/.bitcoin /home/store/app-data/
sudo ln -s /home/store/app-data/.bitcoin /home/bitcoin/
sudo chown -R joinmarket:joinmarket /home/joinmarket/.bitcoin/
sudo systemctl start signetd
fi
}
function makeEncryptedFolder() {
# TODO
# make encrypted file
# mount to /mnt/encrypted/
# move all from app-data
sudo mv /home/store/app-data /mnt/encrypted/
# symlink
sudo ln -s /mnt/encrypted/app-data /home/store/
}
function downloadSnapShot() {
if [ $# -eq 0 ] || [ "$1" = "pruned.host4coins.net" ]; then
hashFileName="sha256sum.txt"
hashFileSigName="sha256sum.txt.asc"
downloadDomain="pruned.host4coins.net/blocks"
pgpKeyLink="https://keys.openpgp.org/vks/v1/by-fingerprint/440C15769D19E6908CC1DDB23070DE9772DB8A48"
elif [ "$1" = "prunednode.today" ]; then
hashFileName="latest.signed.txt"
downloadDomain="prunednode.today"
pgpKeyLink="https://stepansnigirev.com/ss-specter-release.asc"
fi
echo "# Check available diskspace"
FREE=$(df -k --output=avail "$PWD" | tail -n1) # df -k not df -h
if [ $FREE -lt 21000000 ]; then
echo "# The free space is only $FREE bytes!"
echo "# Would need ~21GB free space to download and extract the snapshot."
echo "# Press ENTER to continue to download regardless or CTRL+C to exit."
read key
else
echo "# OK, more than 21GB is free!"
fi
sudo -u joinmarket mkdir /home/joinmarket/download 2>/dev/null
cd /home/joinmarket/download || exit 1
sudo rm $hashFileName 2>/dev/null
echo "# Downloading $hashFileName ..."
wget --prefer-family=ipv4 -O $hashFileName https://$downloadDomain/$hashFileName || exit 1
downloadFileName=$(grep .zip <$hashFileName | awk '{print $2}')
downloadLink="https://$downloadDomain/$downloadFileName"
echo "# Import the signing key"
curl -sS "$pgpKeyLink" | gpg --import || exit 1
echo "# Verifying the signature of the hash ..."
if [ ${#hashFileSigName} -gt 0 ]; then
wget --prefer-family=ipv4 -O $hashFileSigName https://$downloadDomain/$hashFileSigName || exit 1
fi
if ! gpg --verify $hashFileSigName $hashFileName; then
echo "# Invalid signature on $hashFileName"
echo "# Press ENTER to remove the invalid file or CTRL+C to abort."
read key
echo "# Removing $hashFileName"
rm -f $hashFileName
exit 1
fi
if [ ! -f $downloadFileName ]; then
echo
echo "# Downloading $downloadLink ..."
echo
wget --prefer-family=ipv4 -O $downloadFileName $downloadLink || exit 1
fi
echo "# Verifying the hash (takes time) ..."
if sha256sum -c $hashFileName --ignore-missing; then
echo
echo "# The PGP signature and the hash of the downloaded snapshot is correct"
else
echo
echo "# Download failed --> the PGP signature did not match / signature(${goodSignature})"
echo "# Press ENTER to remove the invalid files or CTRL+C to abort."
read key
echo "# Removing the downloaded files"
rm -f $hashFileName
rm -f $downloadFileName
exit 1
fi
echo "# Extracting to /home/store/app-data/.bitcoin ..."
FREE=$(df -k --output=avail "$PWD" | tail -n1) # df -k not df -h
if [ $FREE -lt 11000000 ]; then
echo "# The free space is only $FREE bytes!"
echo "# Would need ~11GB free space to extract the snapshot."
echo "# Press ENTER to continue to extract it regardless or CTRL+C to exit."
read key
else
echo "# OK, more than 11GB is free!"
fi
addUserStore
if [ ! -d /home/store/app-data/.bitcoin ]; then
sudo mkdir -p /home/store/app-data/.bitcoin
fi
echo "# Making sure user: bitcoin exists"
sudo adduser --system --group --shell /bin/bash --home /home/bitcoin bitcoin
echo "Copy the skeleton files for login"
sudo -u bitcoin cp -r /etc/skel/. /home/bitcoin/
sudo chown -R bitcoin:bitcoin /home/store/app-data/.bitcoin
echo "# Add the joinmarket user to the bitcoin group"
sudo usermod -aG bitcoin joinmarket
echo "# Make sure bitcoind is not running"
sudo systemctl stop bitcoind
if sudo -u bitcoin ls /home/bitcoin/.bitcoin/bitcoin.conf; then
echo "# Back up bitcoin.conf"
sudo -u bitcoin mv /home/bitcoin/.bitcoin/bitcoin.conf \
/home/bitcoin/.bitcoin/bitcoin.conf.backup
fi
echo "# Clean old blocks and chainstate"
sudo rm -rf /home/store/app-data/.bitcoin/blocks
sudo rm -rf /home/store/app-data/.bitcoin/chainstate
echo "# Unzip ..."
sudo apt-get install -y unzip
sudo -u bitcoin unzip -o $downloadFileName -d /home/store/app-data/.bitcoin || exit 1
echo "# OK - Decompressed successfully"
echo "# Removing the downloaded files"
rm -f $hashFileName
rm -f $downloadFileName
if sudo -u bitcoin ls /home/bitcoin/.bitcoin/bitcoin.conf.backup; then
echo "# Restore bitcoin.conf"
sudo -u bitcoin mv -f /home/bitcoin/.bitcoin/bitcoin.conf.backup \
/home/bitcoin/.bitcoin/bitcoin.conf
fi
}
function installBitcoinCoreStandalone() {
downloadBitcoinCore
if [ -f /usr/local/bin/bitcoind ]; then
installedVersion=$(/usr/local/bin/bitcoind --version | grep version)
echo "${installedVersion} is already installed"
else
echo "# Adding the user: bitcoin"
sudo adduser --system --group --shell /bin/bash --home /home/bitcoin bitcoin
echo "Copy the skeleton files for login"
sudo -u bitcoin cp -r /etc/skel/. /home/bitcoin/
echo "# Add the joinmarket user to the bitcoin group"
sudo usermod -aG bitcoin joinmarket
echo "# Installing Bitcoin Core v${bitcoinVersion}"
cd /home/joinmarket/download/bitcoin-${bitcoinVersion}/bin/ || exit 1
sudo install -m 0755 -o root -g root -t /usr/local/bin/ ./*
fi
if ! sudo -u bitcoin /usr/local/bin/bitcoind --version | grep "Bitcoin Core version"; then
echo
echo "# BUILD FAILED --> Was not able to install Bitcoin Core)"
exit 1
fi
# bitcoin.conf
if [ -f /home/store/app-data/.bitcoin/bitcoin.conf ]; then
if [ $(sudo -u bitcoin grep -c rpcpassword </home/store/app-data/.bitcoin/bitcoin.conf) -eq 0 ]; then
echo "# Removing old bitcoin.conf without rpcpassword configured"
sudo rm /home/store/app-data/.bitcoin/bitcoin.conf
fi
fi
echo "# symlink /home/store/app-data/.bitcoin to /home/bitcoin/"
sudo rm -rf /home/bitcoin/.bitcoin # not a symlink, delete
sudo mkdir -p /home/store/app-data/.bitcoin
sudo ln -s /home/store/app-data/.bitcoin /home/bitcoin/
if [ ! -f /home/bitcoin/.bitcoin/bitcoin.conf ]; then
randomRPCpass=$(tr </dev/urandom -dc _A-Z-a-z-0-9 | head -c20)
echo "
# bitcoind configuration for mainnet
# Connection settings
rpcuser=joininbox
rpcpassword="$randomRPCpass"
prune=1000
server=1
fallbackfee=0.0002
onlynet=onion
proxy=127.0.0.1:9050
" | sudo tee /home/bitcoin/.bitcoin/bitcoin.conf
else
echo "# /home/bitcoin/.bitcoin/bitcoin.conf is present"
fi
sudo chown -R bitcoin:bitcoin /home/store/app-data/.bitcoin
sudo chown -R bitcoin:bitcoin /home/bitcoin/
}
function installMainnet() {
source /home/joinmarket/_functions.bitcoincore.sh
removeSignetdService
sudo systemctl stop bitcoind
# /etc/systemd/system/bitcoind.service
echo "
[Unit]
Description=Bitcoin daemon on mainnet
[Service]
Environment='MALLOC_ARENA_MAX=1'
ExecStart=/usr/local/bin/bitcoind \\
-daemonwait \\
-conf=/home/bitcoin/.bitcoin/bitcoin.conf \\
-datadir=/home/bitcoin/.bitcoin
PermissionsStartOnly=true
# Process management
####################
Type=forking
Restart=on-failure
TimeoutStartSec=infinity
TimeoutStopSec=600
# Directory creation and permissions
####################################
# Run as bitcoin:bitcoin
User=bitcoin
Group=bitcoin
StandardOutput=null
StandardError=journal
# Hardening measures
####################
# Provide a private /tmp and /var/tmp.
PrivateTmp=true
# Mount /usr, /boot/ and /etc read-only for the process.
ProtectSystem=full
# Disallow the process and all of its children to gain
# new privileges through execve().
NoNewPrivileges=true
# Use a new /dev namespace only populated with API pseudo devices
# such as /dev/null, /dev/zero and /dev/random.
PrivateDevices=true
# Deny the creation of writable and executable memory mappings.
MemoryDenyWriteExecute=true
[Install]
WantedBy=multi-user.target
" | sudo tee /etc/systemd/system/bitcoind.service
sudo systemctl daemon-reload
sudo systemctl enable bitcoind
echo "# OK - the bitcoind.service is now enabled"
# add aliases
if ! grep "alias bitcoin-cli" /home/joinmarket/_aliases.sh; then
sudo bash -c "echo 'alias bitcoin-cli=\"sudo -u bitcoin /usr/local/bin/bitcoin-cli\"' >> /home/joinmarket/_aliases.sh"
fi
if ! grep "alias bitcoind" /home/joinmarket/_aliases.sh; then
sudo bash -c "echo 'alias bitcoind=\"sudo -u bitcoin /usr/local/bin/bitcoind\"' >> /home/joinmarket/_aliases.sh"
fi
if ! grep "alias bitcoinlog" /home/joinmarket/_aliases.sh; then
sudo bash -c "echo 'alias bitcoinlog=\"sudo tail -f /home/bitcoin/.bitcoin/debug.log\"' >> /home/joinmarket/_aliases.sh"
fi
if ! grep "alias bitcoinconf" /home/joinmarket/_aliases.sh; then
sudo bash -c "echo 'alias bitcoinconf=\"sudo nano /home/bitcoin/.bitcoin/bitcoin.conf\"' >> /home/joinmarket/_aliases.sh"
fi
# set joinin.conf value
/home/joinmarket/set.value.sh set network mainnet ${joininConfPath}
sudo systemctl start bitcoind
echo
echo "# Installed $(sudo -u bitcoin /usr/local/bin/bitcoind --version | grep version)"
echo
echo "# Monitor the bitcoind with: sudo tail -f /home/bitcoin/.bitcoin/mainnet/debug.log"
echo
if [ ! -d /home/bitcoin/.bitcoin/wallets/watch-only-descriptor-wallet ]; then
echo "# Create watch-only-descriptor-wallet ..."
sleep 10
sudo -u bitcoin /usr/local/bin/bitcoin-cli -named createwallet wallet_name=watch-only-descriptor-wallet descriptors=true disable_private_keys=true
fi
}