mirror of
https://github.com/openoms/joininbox.git
synced 2026-08-13 12:33:14 +02:00
Compare commits
41 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
16fc83f47d | ||
|
|
54473190c8 | ||
|
|
dfb33c8ab0 | ||
|
|
aa8d79c97d | ||
|
|
efdf660969 | ||
|
|
554a20a297 | ||
|
|
7a61e3b357 | ||
|
|
f92be4e5b3 | ||
|
|
ea675689c5 | ||
|
|
e69d6006a4 | ||
|
|
1b9eca2447 | ||
|
|
a91cdc3657 | ||
|
|
56b06fafa4 | ||
|
|
304144e881 | ||
|
|
b5bc21ad7b | ||
|
|
9594fbf20e | ||
|
|
44e095e324 | ||
|
|
601eede8b5 | ||
|
|
19ffa45e66 | ||
|
|
8afc78dcf4 | ||
|
|
41a5c9e573 | ||
|
|
b532dbeab3 | ||
|
|
7800d632a5 | ||
|
|
18d28bedf4 | ||
|
|
aaa22e375b | ||
|
|
c75ddacfc9 | ||
|
|
6b606760eb | ||
|
|
b9360c1008 | ||
|
|
622847e80e | ||
|
|
c87e06c829 | ||
|
|
efad4a01ff | ||
|
|
e2e540ccbd | ||
|
|
d961839137 | ||
|
|
0126005b90 | ||
|
|
11c2e0dacd | ||
|
|
dec26c7732 | ||
|
|
ea5187c933 | ||
|
|
a61da715ca | ||
|
|
0daac40e21 | ||
|
|
7b2166d124 | ||
|
|
8f61362f9b |
54 changed files with 2068 additions and 788 deletions
15
.editorconfig
Normal file
15
.editorconfig
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# EditorConfig helps maintain consistent coding styles
|
||||
# https://editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
6
.github/workflows/amd64-image-build.yml
vendored
6
.github/workflows/amd64-image-build.yml
vendored
|
|
@ -1,5 +1,9 @@
|
|||
name: amd64-image-build
|
||||
|
||||
concurrency:
|
||||
group: amd64-image-build-${{ github.head_ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
|
|
@ -61,7 +65,7 @@ jobs:
|
|||
sha256sum joininbox-amd64-debian.qcow2.gz > joininbox-amd64-debian.qcow2.gz.sha256
|
||||
|
||||
- name: Upload the image and checksums
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: joininbox-amd64-image-${{ env.BUILD_DATE }}-${{ env.BUILD_VERSION }}
|
||||
path: |
|
||||
|
|
|
|||
65
.github/workflows/amd64-image-test.yml
vendored
Normal file
65
.github/workflows/amd64-image-test.yml
vendored
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
name: amd64-image-test
|
||||
|
||||
concurrency:
|
||||
group: amd64-image-test-${{ github.event.workflow_run.id || inputs.run_id || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["amd64-image-build"]
|
||||
types: [completed]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
run_id:
|
||||
description: "amd64-image-build workflow run ID to test"
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
bats-image-test:
|
||||
name: Run Bats against amd64 image artifact
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 240
|
||||
if: ${{ github.event_name != 'workflow_run' || (github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.head_repository.full_name == github.repository) }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
repository: ${{ github.event.workflow_run.head_repository.full_name || github.repository }}
|
||||
ref: ${{ github.event.workflow_run.head_sha || github.ref }}
|
||||
|
||||
- name: Check out bats-core
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: bats-core/bats-core
|
||||
# bats-core v1.12.0
|
||||
ref: 713504bc0224a19b3d7c7958c18dc07f64f54b44
|
||||
path: .bats-core
|
||||
persist-credentials: false
|
||||
|
||||
- name: Download amd64 image artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
github-token: ${{ github.token }}
|
||||
run-id: ${{ github.event.workflow_run.id || inputs.run_id }}
|
||||
pattern: joininbox-amd64-image-*
|
||||
path: artifacts
|
||||
merge-multiple: true
|
||||
|
||||
- name: Verify and decompress image
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
cd artifacts
|
||||
sha256sum -c joininbox-amd64-debian.qcow2.gz.sha256
|
||||
gzip -dk joininbox-amd64-debian.qcow2.gz
|
||||
sha256sum -c joininbox-amd64-debian.qcow2.sha256
|
||||
|
||||
- name: Run image Bats tests
|
||||
timeout-minutes: 30
|
||||
run: ci/amd64/test.amd64-image-bats.sh "${GITHUB_WORKSPACE}/artifacts/joininbox-amd64-debian.qcow2"
|
||||
6
.github/workflows/arm64-rpi-image-build.yml
vendored
6
.github/workflows/arm64-rpi-image-build.yml
vendored
|
|
@ -1,5 +1,9 @@
|
|||
name: arm64-rpi-image-build
|
||||
|
||||
concurrency:
|
||||
group: arm64-rpi-image-build-${{ github.head_ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
|
|
@ -68,7 +72,7 @@ jobs:
|
|||
sha256sum joininbox-arm64-rpi.img.gz > joininbox-arm64-rpi.img.gz.sha256
|
||||
|
||||
- name: Upload the image and checksums
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: joininbox-arm64-rpi-image-${{ env.BUILD_DATE }}-${{ env.BUILD_VERSION }}
|
||||
path: |
|
||||
|
|
|
|||
60
.github/workflows/packer-syntax-check.yml
vendored
Normal file
60
.github/workflows/packer-syntax-check.yml
vendored
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
name: Packer Syntax Check
|
||||
|
||||
concurrency:
|
||||
group: packer-syntax-check-${{ github.head_ref || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
paths:
|
||||
- '.github/workflows/packer-syntax-check.yml'
|
||||
- 'ci/amd64/**/*.pkr.hcl'
|
||||
- 'ci/amd64/**/*.pkrvars.hcl'
|
||||
- 'ci/amd64/packer.build.amd64-debian.sh'
|
||||
- 'ci/arm64-rpi/**/*.pkr.hcl'
|
||||
- 'ci/arm64-rpi/**/*.pkrvars.hcl'
|
||||
- 'ci/arm64-rpi/arm64-rpi.sh'
|
||||
pull_request:
|
||||
branches: [ "master" ]
|
||||
paths:
|
||||
- '.github/workflows/packer-syntax-check.yml'
|
||||
- 'ci/amd64/**/*.pkr.hcl'
|
||||
- 'ci/amd64/**/*.pkrvars.hcl'
|
||||
- 'ci/amd64/packer.build.amd64-debian.sh'
|
||||
- 'ci/arm64-rpi/**/*.pkr.hcl'
|
||||
- 'ci/arm64-rpi/**/*.pkrvars.hcl'
|
||||
- 'ci/arm64-rpi/arm64-rpi.sh'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
validate-packer-syntax:
|
||||
name: Validate Packer Syntax
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Packer
|
||||
uses: hashicorp/setup-packer@v3
|
||||
|
||||
- name: Show Packer version
|
||||
run: packer version
|
||||
|
||||
- name: Validate amd64 templates (syntax only)
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
mapfile -t templates < <(find ci/amd64 ci/arm64-rpi -type f \( -name '*.pkr.hcl' -o -name '*.pkrvars.hcl' \) | sort)
|
||||
|
||||
if [ ${#templates[@]} -eq 0 ]; then
|
||||
echo "No Packer templates found under ci/amd64 or ci/arm64-rpi"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for template in "${templates[@]}"; do
|
||||
echo "Validating $template"
|
||||
packer validate -syntax-only "$template"
|
||||
done
|
||||
19
.github/workflows/test-shellcheck.yml
vendored
Normal file
19
.github/workflows/test-shellcheck.yml
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
name: "Test Shellcheck"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: ["master"]
|
||||
pull_request:
|
||||
branches: ["master"]
|
||||
|
||||
jobs:
|
||||
shellcheck:
|
||||
name: Run Shellcheck
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Run ShellCheck
|
||||
uses: ludeeus/action-shellcheck@master
|
||||
with:
|
||||
severity: error
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -1,3 +1,5 @@
|
|||
scripts/wallets
|
||||
ci/arm64-rpi/.packer*
|
||||
ci/arm64-rpi/joininbox-arm64-rpi*
|
||||
ci/amd64/builds
|
||||
scripts/jam-remote/download
|
||||
|
|
|
|||
187
FAQ.md
187
FAQ.md
|
|
@ -10,7 +10,6 @@
|
|||
- [Log in through SSH using a hardware wallet](#log-in-through-ssh-using-a-hardware-wallet)
|
||||
- [SSH through Tor from Linux](#ssh-through-tor-from-linux)
|
||||
- [Allow Tor to connect to localhost](#allow-tor-to-connect-to-localhost)
|
||||
- [Set up Armbian on the Hardkernel Odroid HC1 / XU4](#set-up-armbian-on-the-hardkernel-odroid-hc1--xu4)
|
||||
- [Download and verify Raspbian SDcard image for a Raspberry Pi](#download-and-verify-raspbian-sdcard-image-for-a-raspberry-pi)
|
||||
- [Error when connecting to a full node remotely through Tor](#error-when-connecting-to-a-full-node-remotely-through-tor)
|
||||
- [Erase the joinmarket user and the /home/joinmarket folder](#erase-the-joinmarket-user-and-the-homejoinmarket-folder)
|
||||
|
|
@ -31,6 +30,7 @@
|
|||
- [Wallet recovery](#wallet-recovery)
|
||||
- [on JoininBox](#on-joininbox)
|
||||
- [on the remote node](#on-the-remote-node)
|
||||
- [Migrating from legacy wallet.dat to descriptor wallet](#migrating-from-legacy-walletdat-to-descriptor-wallet)
|
||||
- [USB SSD recommendation](#usb-ssd-recommendation)
|
||||
- [Pruned node notes](#pruned-node-notes)
|
||||
- [External drive](#external-drive)
|
||||
|
|
@ -172,55 +172,10 @@ Use `ssh` with `torsocks` on the desktop (needs Tor installed):
|
|||
* Restart Tor:
|
||||
`sudo systemctl restart tor`
|
||||
|
||||
## Set up Armbian on the Hardkernel Odroid HC1 / XU4
|
||||
* Download the base image (`.img.gz`), the `.sha` and `.asc` file
|
||||
https://www.armbian.com/odroid-xu4/
|
||||
* Verify: https://docs.armbian.com/User-Guide_Getting-Started/#how-to-check-download-authenticity
|
||||
```bash
|
||||
gpg --keyserver ha.pool.sks-keyservers.net --recv-key DF00FAF1C577104B50BF1D0093D6889F9F0E78D5
|
||||
# gpg: key 93D6889F9F0E78D5: public key "Igor Pecovnik # <igor@armbian. com>" imported
|
||||
# gpg: Total number processed: 1
|
||||
# gpg: imported: 1
|
||||
gpg --verify Armbian_21.02.3_Odroidxu4_buster_legacy_4.14.222.img.xz.asc
|
||||
# gpg: assuming signed data in 'Armbian_21.02.3_Odroidxu4_buster_legacy_4.14.222.img.xz'
|
||||
# gpg: Signature made Tue 09 Mar 2021 03:00:30 GMT
|
||||
# gpg: using RSA key DF00FAF1C577104B50BF1D0093D6889F9F0E78D5
|
||||
# gpg: Good signature from "Igor Pecovnik <igor@armbian.com>" [unknown]
|
||||
# gpg: aka "Igor Pecovnik (Ljubljana, Slovenia) <igor.pecovnik@gmail.com>" [unknown]
|
||||
# gpg: WARNING: This key is not certified with a trusted signature!
|
||||
# gpg: There is no indication that the signature belongs to the owner.
|
||||
# Primary key fingerprint: DF00 FAF1 C577 104B 50BF 1D00 93D6 889F 9F0E 78D5
|
||||
shasum -c Armbian_21.02.3_Odroidxu4_buster_legacy_4.14.222.img.xz.sha
|
||||
# Armbian_21.02.3_Odroidxu4_buster_legacy_4.14.222.img.xz: OK
|
||||
```
|
||||
* Preparation
|
||||
Make sure you have a good & reliable SD card and a proper power supply. Archives can be uncompressed with 7-Zip on Windows, Keka on OS X and 7z on Linux (apt-get install p7zip-full). RAW images can be written with Etcher (all OS).
|
||||
* Boot
|
||||
Insert the SD card into the slot, connect a cable to your network if possible or a display and power your board. (First) boot (with DHCP) takes up to 35 seconds with a class 10 SD Card.
|
||||
* Login
|
||||
Log in as: `root` Password: `1234`. Then you are prompted to change this password (US-Keyboard setting). When done, you are asked to create a normal user-account for your everyday tasks.
|
||||
* Change the password.
|
||||
* Create a new user called `joinmarket` and set the password (the password will be changed to `joininbox`).
|
||||
Keep pressing [ENTER] to use the default user information.
|
||||
* Continue to [install JoininBox](README.md#install-joininbox)
|
||||
|
||||
## Download and verify Raspbian SDcard image for a Raspberry Pi
|
||||
To be able to open the JoinMarket-QT GUI on the desktop from the RPI
|
||||
need to use the Raspberry Pi OS (32-bit) with desktop image
|
||||
* Download image:
|
||||
https://downloads.raspberrypi.org/raspios_armhf/images/raspios_armhf-2020-05-28/2020-05-27-raspios-buster-armhf.zip
|
||||
* Download signature:
|
||||
https://downloads.raspberrypi.org/raspios_armhf/images/raspios_armhf-2020-05-28/2020-05-27-raspios-buster-armhf.zip.sig
|
||||
* Import PGP pubkey:
|
||||
`curl https://www.raspberrypi.org/raspberrypi_downloads.gpg.key | gpg --import`
|
||||
* Verify the image:
|
||||
`gpg --verify 2020-05-27-raspios-buster-armhf.zip.sig`
|
||||
* Flash the image to an SDcard, can use the [Raspberry Pi Imager](https://www.raspberrypi.org/downloads/)
|
||||
* put a file called simply: `ssh` to the root of the sdcard.
|
||||
Read more on [how to gain ssh access here](https://www.raspberrypi.org/documentation/remote-access/ssh/).
|
||||
* boot up the RPi and log in with ssh to:
|
||||
`pi@LAN_IP_ADDRESS`
|
||||
The default password is: `raspberry`
|
||||
* Download [Raspberry Pi Imager](https://www.raspberrypi.com/software/)
|
||||
* enable the ssh login in the
|
||||
* Flash the image to a min 32GB Endurance type SDcard
|
||||
* Continue to [install JoininBox](README.md#install-joininbox)
|
||||
|
||||
## Error when connecting to a full node remotely through Tor
|
||||
|
|
@ -241,7 +196,7 @@ The default password is: `raspberry`
|
|||
server=1
|
||||
daemon=1
|
||||
disablewallet=0
|
||||
main.wallet=wallet.dat
|
||||
main.wallet=watch-only-descriptor-wallet
|
||||
|
||||
# Connection settings
|
||||
rpcuser=REDACTED
|
||||
|
|
@ -474,7 +429,7 @@ JoinMarket docs:
|
|||
* https://github.com/JoinMarket-Org/joinmarket-clientserver/blob/master/docs/USAGE.md#recover
|
||||
|
||||
### on JoininBox
|
||||
* Connect the remote bitcoind with `CONFIG` -> `CONNECT` menu so it checks if the connection is successful. It will also set the remote watch-only wallet in bitcoind to "joininbox" so will need to rescan that after recovering an old wallet with previously used addresses.
|
||||
* Connect the remote bitcoind with `CONFIG` -> `CONNECT` menu so it checks if the connection is successful. It will also set the remote watch-only-descriptor-wallet in bitcoind to "joininbox" so will need to rescan that after recovering an old wallet with previously used addresses.
|
||||
|
||||
* When using the CLI and connecting to the remote node over Tor, you will need to use the script with the torsocks prefix like:
|
||||
`torsocks python3 wallet-tool.py --recoversync -g 20 ~/.joinmarket/wallets/wallet.jmdat`
|
||||
|
|
@ -483,7 +438,7 @@ JoinMarket docs:
|
|||
* Use the menu option `WALLET` -> `RESCAN` or follow manually
|
||||
* the wallet defined as
|
||||
`rpc_wallet =`
|
||||
in the joinmarket.cfg is the wallet which is used as watch only in the remote bitcoind.
|
||||
in the joinmarket.cfg is the wallet which is used as a watch-only-descriptor-wallet in the remote bitcoind.
|
||||
You need to run rescanblockchain on that wallet in bitcoind after importing the joinmarket wallet.
|
||||
* The wallet is set in the joinmarket.cfg (by default called `joininbox` should show up when you run:
|
||||
`bitcoin-cli listwallets`
|
||||
|
|
@ -493,8 +448,67 @@ You need to run rescanblockchain on that wallet in bitcoind after importing the
|
|||
Rescanning from the first SegWit block is sufficient for the default SegWit wallets.
|
||||
|
||||
* Monitor progress (on a RaspiBlitz):
|
||||
`sudo tail -fn 100 /mnt/hdd/bitcoin/debug.log`
|
||||
`sudo tail -fn 100 /mnt/hdd/app-storage/bitcoin/debug.log`
|
||||
Once the rescan is finished you balances should appear in the `INFO` menu (`wallet-tool.py`)
|
||||
|
||||
## Migrating from legacy wallet.dat to descriptor wallet
|
||||
|
||||
Starting with the 0.9.0 version, JoininBox uses Bitcoin Core's descriptor wallets (`watch-only-descriptor-wallet`) instead of the legacy `wallet.dat`. This change provides better compatibility with modern Bitcoin Core versions (v26+) and aligns with Bitcoin Core's default wallet format.
|
||||
|
||||
### Why this change?
|
||||
|
||||
Bitcoin Core has deprecated BDB (Berkeley DB) wallets in favor of descriptor wallets. The new descriptor wallets:
|
||||
- Are the default in Bitcoin Core v26+
|
||||
- Don't require the `deprecatedrpc=create_bdb` configuration
|
||||
- Have better performance and features
|
||||
- Are actively maintained and improved
|
||||
|
||||
### How automatic migration works
|
||||
|
||||
When `rpc_wallet_file` is still set to `wallet.dat`, JoininBox queries the connected Bitcoin Core node using RPC before changing the configuration:
|
||||
|
||||
- Bitcoin Core v30.0 and newer: JoininBox atomically changes `rpc_wallet_file` to `watch-only-descriptor-wallet`, creates or loads that descriptor wallet, and displays the migration notice when the old `wallet.dat` is present.
|
||||
- Bitcoin Core v29.x and earlier: JoininBox keeps using `wallet.dat` and does not start automatic migration.
|
||||
- Version unavailable: JoininBox leaves `wallet.dat` configured rather than migrating without confirming compatibility.
|
||||
|
||||
The migration does not rename, modify, or delete the old `wallet.dat`. It changes which Bitcoin Core wallet JoinMarket uses for watch-only address imports and transaction history.
|
||||
|
||||
### Migration steps for existing users
|
||||
|
||||
If you're upgrading from a previous version of JoininBox that used `wallet.dat`, follow these steps:
|
||||
|
||||
1. **The migration notice will appear automatically on Bitcoin Core v30.0 and newer**
|
||||
When you first use any wallet-related function after updating, JoininBox checks the connected Bitcoin Core version. On v30.0 and newer it switches the configured RPC wallet to `watch-only-descriptor-wallet`, detects the old `wallet.dat`, and displays a migration notice. Bitcoin Core v29.x and earlier continue using `wallet.dat` without starting the automatic migration.
|
||||
|
||||
2. **Open each JoinMarket wallet**
|
||||
Go to `WALLET` -> `DISPLAY` and open each of your JoinMarket wallets (`.jmdat` files) at least once. This imports the addresses into the new `watch-only-descriptor-wallet` in Bitcoin Core.
|
||||
|
||||
3. **Run a blockchain rescan**
|
||||
After opening all your wallets, go to `WALLET` -> `RESCAN` and enter a blockheight:
|
||||
- Use `481824` (first SegWit block) for wallets created after August 2017
|
||||
- Can use a later blockheight if you know when your wallet had its first deposit
|
||||
|
||||
4. **Wait for the rescan to complete**
|
||||
The rescan can take several hours depending on the blockheight and your hardware. Monitor progress with:
|
||||
```bash
|
||||
# On standalone JoininBox:
|
||||
sudo tail -f /home/bitcoin/.bitcoin/debug.log
|
||||
|
||||
# On RaspiBlitz:
|
||||
sudo tail -f /mnt/hdd/bitcoin/debug.log
|
||||
```
|
||||
|
||||
5. **Verify your balances**
|
||||
Once the rescan completes, check your wallet balances with `WALLET` -> `DISPLAY`.
|
||||
|
||||
### Notes
|
||||
|
||||
- The old `wallet.dat` is not deleted and remains in Bitcoin Core
|
||||
- Automatic migration only runs when the connected Bitcoin Core version is v30.0 or newer
|
||||
- You only need to perform this migration once
|
||||
- The migration notice will not appear again after you acknowledge it
|
||||
- If you have issues, you can reset the migration flag by removing `walletMigrationDone=true` from `/home/joinmarket/joinin.conf`
|
||||
|
||||
## USB SSD recommendation
|
||||
**JoininBox operates on the minimum viable hardware under the assumption that the seed (and passphrase) of the wallets used is safely backed up and can be recovered fully**
|
||||
* The above warning is especially true for SDcard as they fail often, use a good quality one.
|
||||
|
|
@ -565,35 +579,16 @@ Alternatively to a pruned node there could be a larger >400 GB storage connected
|
|||
# -rw------- 1 bitcoin bitcoin 1521305 Mar 21 10:38 peers.dat
|
||||
# -rw-r--r-- 1 bitcoin bitcoin 7 Mar 21 10:08 settings.json
|
||||
# drwx------ 34 bitcoin bitcoin 4096 Dec 7 23:39 specter
|
||||
# drwx------ 2 bitcoin bitcoin 4096 Mar 21 10:38 wallet.dat
|
||||
# drwx------ 2 bitcoin bitcoin 4096 Mar 21 10:38 watch-only-descriptor-wallet
|
||||
installMainnet
|
||||
# Failed to stop bitcoind.service: Unit bitcoind.service not loaded.
|
||||
#
|
||||
# [Unit]
|
||||
# Description=Bitcoin daemon on mainnet
|
||||
# [Service]
|
||||
# User=bitcoin
|
||||
# Group=bitcoin
|
||||
# Type=forking
|
||||
# PIDFile=/home/bitcoin/bitcoin/bitcoind.pid
|
||||
# ExecStart=/home/bitcoin/bitcoin/bitcoind -daemon -pid=/home/bitcoin/bitcoin/bitcoind.pid
|
||||
# Restart=always
|
||||
# TimeoutSec=120
|
||||
# RestartSec=30
|
||||
# StandardOutput=null
|
||||
# StandardError=journal
|
||||
#
|
||||
# [Install]
|
||||
# WantedBy=multi-user.target
|
||||
#
|
||||
# Created symlink /etc/systemd/system/multi-user.target.wants/bitcoind.service → /etc/systemd/system/bitcoind.service.
|
||||
...
|
||||
# # OK - the bitcoind.service is now enabled
|
||||
#
|
||||
# # Installed Bitcoin Core version v0.21.0
|
||||
#
|
||||
# # Monitor the bitcoind with: sudo tail -f /home/bitcoin/.bitcoin/mainnet/debug.log
|
||||
#
|
||||
# # Create wallet.dat ...
|
||||
# # Create watch-only-descriptor-wallet ...
|
||||
# error code: -28
|
||||
# error message:
|
||||
# Loading block index...
|
||||
|
|
@ -604,48 +599,6 @@ Alternatively to a pruned node there could be a larger >400 GB storage connected
|
|||
## IRC server settings
|
||||
* See the most up to date configuration in:
|
||||
https://github.com/JoinMarket-Org/joinmarket-clientserver/blob/master/jmclient/jmclient/configure.py
|
||||
* The latest setting with Tor enabled:
|
||||
```
|
||||
[MESSAGING:server1]
|
||||
#host = irc.darkscience.net
|
||||
channel = joinmarket-pit
|
||||
port = 6697
|
||||
usessl = true
|
||||
#socks5 = false
|
||||
socks5_host = localhost
|
||||
socks5_port = 9050
|
||||
#for tor
|
||||
host = darkirc6tqgpnwd3blln3yfv5ckl47eg7llfxkmtovrv7c7iwohhb6ad.onion
|
||||
socks5 = true
|
||||
|
||||
[MESSAGING:server2]
|
||||
#host = irc.hackint.org
|
||||
channel = joinmarket-pit
|
||||
#port = 6697
|
||||
#usessl = true
|
||||
#socks5 = false
|
||||
socks5_host = localhost
|
||||
socks5_port = 9050
|
||||
#for tor
|
||||
host = ncwkrwxpq2ikcngxq3dy2xctuheniggtqeibvgofixpzvrwpa77tozqd.onion
|
||||
port = 6667
|
||||
usessl = false
|
||||
socks5 = true
|
||||
|
||||
[MESSAGING:server3]
|
||||
#host = agora.anarplex.net
|
||||
channel = joinmarket-pit
|
||||
#port = 14716
|
||||
#usessl = true
|
||||
#socks5 = false
|
||||
socks5_host = localhost
|
||||
socks5_port = 9050
|
||||
#for tor
|
||||
host = vxecvd6lc4giwtasjhgbrr3eop6pzq6i5rveracktioneunalgqlwfad.onion
|
||||
port = 6667
|
||||
usessl = false
|
||||
socks5 = true
|
||||
```
|
||||
|
||||
## Install JoinMarket without the QT GUI and dependencies
|
||||
* Run the build script with the options `BRANCH` `GITHUBUSER` `without-qt`:
|
||||
|
|
|
|||
9
Makefile
9
Makefile
|
|
@ -35,3 +35,12 @@ arm64-rpi-image:
|
|||
# Compute checksum of the compressed image
|
||||
cd ci/arm64-rpi && \
|
||||
sha256sum joininbox-arm64-rpi.img.gz > joininbox-arm64-rpi.img.gz.sha256
|
||||
|
||||
release-tag:
|
||||
@if [ -z "$(TAG)" ]; then \
|
||||
echo "Error: TAG parameter is required. Usage: make release-tag TAG=v0.7.4"; \
|
||||
exit 1; \
|
||||
fi
|
||||
@echo "Creating signed tag $(TAG) and pushing to origin..."
|
||||
git tag -s $(TAG) -m "$(TAG)" && git push origin $(TAG)
|
||||
@echo "Successfully created and pushed signed tag $(TAG)"
|
||||
|
|
|
|||
18
README.md
18
README.md
|
|
@ -23,7 +23,7 @@ A minimalistic, security focused linux environment for JoinMarket with a termina
|
|||
- [Features](#features)
|
||||
- [Required Hardware](#required-hardware)
|
||||
- [A computer running a Debian / Ubuntu Linux flavour.](#a-computer-running-a-debian--ubuntu-linux-flavour)
|
||||
- [RaspberryPi 4 or 3](#raspberrypi-4-or-3)
|
||||
- [RaspberryPi 5 or 4](#raspberrypi-5-or-4)
|
||||
- [VPS eg: host4coins.net](#vps-eg-host4coinsnet)
|
||||
- [Set up using an SDcard image](#set-up-using-an-sdcard-image)
|
||||
- [Set up JoininBox on Linux](#set-up-joininbox-on-linux)
|
||||
|
|
@ -32,7 +32,6 @@ A minimalistic, security focused linux environment for JoinMarket with a termina
|
|||
- [More info](#more-info)
|
||||
- [About JoinMarket](#about-joinmarket)
|
||||
- [Forums](#forums)
|
||||
- [Donations](#donations)
|
||||
|
||||
## Features
|
||||
|
||||
|
|
@ -44,19 +43,19 @@ A minimalistic, security focused linux environment for JoinMarket with a termina
|
|||
* RaspiBlitz over [LAN or Tor](prepare_remote_node.md#raspiblitz)
|
||||
* RoninDojo over [LAN or Tor](prepare_remote_node.md#ronindojo)
|
||||
* Start a pruned node from https://pruned.host4coins.net/blocks
|
||||
* JoininBox is part the RaspiBlitz SERVICES
|
||||
* JoininBox is part of the RaspiBlitz SERVICES
|
||||
|
||||
**The addresses, transactions and balances of JoinMarket can be seen in the watch-only wallet of the connected node.**
|
||||
**The addresses, transactions and balances of JoinMarket can be seen in the watch-only-descriptor-wallet of the connected node.**
|
||||
* use your own or a trusted node
|
||||
* to protect privacy in case of physical access use disk encryption
|
||||
|
||||
## Required Hardware
|
||||
### A computer running a Debian / Ubuntu Linux flavour.
|
||||
* See the [tested-environments](#tested-environments).
|
||||
### RaspberryPi 4 or 3
|
||||
### RaspberryPi 5 or 4
|
||||
* Power supply (5V 3A and above recommended)
|
||||
* Heatsink case
|
||||
* 32 GB Endurence type SDcard
|
||||
* 32 GB Endurance type SDcard
|
||||
* [(USB SSD to run a pruned bitcoin node locally)](FAQ.md#usb-ssd-recommendation)
|
||||
### VPS eg: [host4coins.net](https://host4coins.net/)
|
||||
Recommended minimum:
|
||||
|
|
@ -123,7 +122,7 @@ Recommended minimum:
|
|||
|
||||
### Install JoininBox
|
||||
* Start as the `root` user or change with:
|
||||
`$ sudo - su`
|
||||
`$ sudo su -`
|
||||
|
||||
* Run the [build script](https://github.com/openoms/joininbox/blob/master/build_joininbox.sh):
|
||||
```bash
|
||||
|
|
@ -162,8 +161,3 @@ the default password is: `joininbox` - will be prompted to change it on the firs
|
|||
* IRC: #joinmarket on [libera.chat](https://libera.chat/) or [hackint.org](https://hackint.org/)
|
||||
* Reddit: <https://www.reddit.com/r/joinmarket/>
|
||||
* Keybase: <https://keybase.io/team/raspiblitz#joinmarket>
|
||||
|
||||
## Donations
|
||||
* For JoinMarket (general): https://bitcoinprivacy.me/joinmarket-donations
|
||||
* To waxwing for JoinMarket: <https://joinmarket.me/donations/>
|
||||
* To openoms for JoininBox (LN + payjoin enabled - open in the [Tor Browser](https://www.torproject.org/)): <http://7tpv3ynajkv6cdocmzitcd4z3xrstp3ic6xtv5om3dc2ned3fffll5qd.onion/apps/4FePMm7m818oppkTYNZRwbDnL6HP/pos>
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ echo "
|
|||
# https://github.com/${githubUser}/joininbox/tree/${wantedBranch}
|
||||
|
||||
# Press ENTER to confirm or CTRL+C to exit"
|
||||
read key
|
||||
read
|
||||
|
||||
echo
|
||||
echo "###################################"
|
||||
|
|
@ -90,7 +90,28 @@ echo "# Preparing the base image"
|
|||
echo "############################"
|
||||
echo
|
||||
|
||||
echo "# Prepare ${baseImage} "
|
||||
echo "# Prevent sleep" # on all platforms https://wiki.debian.org/Suspend
|
||||
systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target
|
||||
mkdir /etc/systemd/sleep.conf.d
|
||||
echo "[Sleep]
|
||||
AllowSuspend=no
|
||||
AllowHibernation=no
|
||||
AllowSuspendThenHibernate=no
|
||||
AllowHybridSleep=no" | tee /etc/systemd/sleep.conf.d/nosuspend.conf
|
||||
mkdir /etc/systemd/logind.conf.d
|
||||
echo "[Login]
|
||||
HandleLidSwitch=ignore
|
||||
HandleLidSwitchDocked=ignore" | tee /etc/systemd/logind.conf.d/nosuspend.conf
|
||||
|
||||
# check if /etc/hosts already has debian entry
|
||||
# prevent "unable to resolve host debian" error
|
||||
isDebianInHosts=$(grep -c "debian" /etc/hosts)
|
||||
if [ ${isDebianInHosts} -eq 0 ]; then
|
||||
echo "# Adding debian to /etc/hosts"
|
||||
echo "127.0.1.1 debian" | tee -a /etc/hosts > /dev/null
|
||||
systemctl restart networking
|
||||
fi
|
||||
|
||||
# special prepare on RPi
|
||||
if [ "${baseimage}" = "raspios" ] || [ "${baseimage}" = "debian_rpi64" ] ||
|
||||
[ "${baseimage}" = "armbian" ]; then
|
||||
|
|
@ -139,17 +160,6 @@ if [ "${baseimage}" = "raspios" ] || [ "${baseimage}" = "debian_rpi64" ]; then
|
|||
echo "$max_usb_current already in $configFile"
|
||||
fi
|
||||
|
||||
# run fsck on sd root partition on every startup to prevent "maintenance login" screen
|
||||
# see: https://github.com/rootzoll/raspiblitz/issues/782#issuecomment-564981630
|
||||
# see https://github.com/rootzoll/raspiblitz/issues/1053#issuecomment-600878695
|
||||
# use command to check last fsck check: sudo tune2fs -l /dev/mmcblk0p2
|
||||
if [ "${tweak_boot_drive}" == "true" ]; then
|
||||
echo "* running tune2fs"
|
||||
tune2fs -c 1 /dev/mmcblk0p2
|
||||
else
|
||||
echo "* skipping tweak_boot_drive"
|
||||
fi
|
||||
|
||||
# edit kernel parameters
|
||||
kernelOptionsFile=/boot/cmdline.txt
|
||||
fsOption1="fsck.mode=force"
|
||||
|
|
@ -266,69 +276,46 @@ echo "##########"
|
|||
echo
|
||||
# apt dependencies for python
|
||||
apt-get install -y python3 virtualenv python3-venv python3-dev python3-wheel python3-jinja2 python3-pip
|
||||
if [ "${cpu}" = "armv7l" ] || [ "${cpu}" = "armv6l" ]; then
|
||||
if [ ! -f "/usr/bin/python3.7" ]; then
|
||||
# install python37
|
||||
pythonVersion="3.7.9"
|
||||
majorPythonVersion=$(echo "$pythonVersion" | awk -F. '{print $1"."$2}')
|
||||
# dependencies
|
||||
apt-get install software-properties-common build-essential libnss3-dev zlib1g-dev libgdbm-dev libncurses5-dev libssl-dev libffi-dev libreadline-dev libsqlite3-dev libbz2-dev -y
|
||||
# download
|
||||
wget --prefer-family=ipv4 --progress=bar:force https://www.python.org/ftp/python/${pythonVersion}/Python-${pythonVersion}.tgz
|
||||
# optional signature for verification
|
||||
wget --prefer-family=ipv4 --progress=bar:force https://www.python.org/ftp/python/${pythonVersion}/Python-${pythonVersion}.tgz.asc
|
||||
# get PGP pubkey of Ned Deily (Python release signing key) <nad@python.org>
|
||||
gpg --recv-key 0D96DF4D4110E5C43FBFB17F2D347EA6AA65421D
|
||||
# check for: Good signature from "Pablo Galindo Salgado <pablogsal@gmail.com>"
|
||||
gpg --verify Python-${pythonVersion}.tgz.asc || exit 1
|
||||
# unzip
|
||||
tar xvf Python-${pythonVersion}.tgz
|
||||
cd Python-${pythonVersion} || exit 1
|
||||
# configure
|
||||
./configure --enable-optimizations
|
||||
# install
|
||||
make altinstall
|
||||
# move the python binary to the expected directory
|
||||
mv "$(which python${majorPythonVersion})" /usr/bin/
|
||||
# check
|
||||
ls -la /usr/bin/python${majorPythonVersion} || exit 1
|
||||
# clean
|
||||
cd ..
|
||||
rm Python-${pythonVersion}.tgz
|
||||
rm -rf Python-${pythonVersion}
|
||||
fi
|
||||
update-alternatives --install /usr/bin/python python /usr/bin/python3.7 1
|
||||
echo "# python calls python3.7"
|
||||
|
||||
if [ -f "/usr/bin/python3.13" ]; then
|
||||
# use python 3.13 if available
|
||||
update-alternatives --install /usr/bin/python python /usr/bin/python3.13 1
|
||||
echo "# python calls python3.13"
|
||||
elif [ -f "/usr/bin/python3.12" ]; then
|
||||
# use python 3.12 if available
|
||||
update-alternatives --install /usr/bin/python python /usr/bin/python3.12 1
|
||||
echo "# python calls python3.12"
|
||||
elif [ -f "/usr/bin/python3.11" ]; then
|
||||
# use python 3.11 if available
|
||||
update-alternatives --install /usr/bin/python python /usr/bin/python3.11 1
|
||||
echo "# python calls python3.11"
|
||||
elif [ -f "/usr/bin/python3.10" ]; then
|
||||
# use python 3.10 if available
|
||||
update-alternatives --install /usr/bin/python python /usr/bin/python3.10 1
|
||||
echo "# python calls python3.10"
|
||||
elif [ -f "/usr/bin/python3.9" ]; then
|
||||
# use python 3.9 if available
|
||||
update-alternatives --install /usr/bin/python python /usr/bin/python3.9 1
|
||||
echo "# python calls python3.9"
|
||||
elif [ -f "/usr/bin/python3.8" ]; then
|
||||
# use python 3.8 if available
|
||||
update-alternatives --install /usr/bin/python python /usr/bin/python3.8 1
|
||||
echo "# python calls python3.8"
|
||||
else
|
||||
if [ -f "/usr/bin/python3.7" ]; then
|
||||
# make sure /usr/bin/python exists (and calls Python3.7)
|
||||
update-alternatives --install /usr/bin/python python /usr/bin/python3.7 1
|
||||
echo "# python calls python3.7"
|
||||
elif [ -f "/usr/bin/python3.8" ]; then
|
||||
# use python 3.8 if available
|
||||
update-alternatives --install /usr/bin/python python /usr/bin/python3.8 1
|
||||
echo "# python calls python3.8"
|
||||
elif [ -f "/usr/bin/python3.9" ]; then
|
||||
# use python 3.9 if available
|
||||
update-alternatives --install /usr/bin/python python /usr/bin/python3.9 1
|
||||
echo "# python calls python3.9"
|
||||
elif [ -f "/usr/bin/python3.10" ]; then
|
||||
# use python 3.10 if available
|
||||
update-alternatives --install /usr/bin/python python /usr/bin/python3.10 1
|
||||
echo "# python calls python3.10"
|
||||
elif [ -f "/usr/bin/python3.11" ]; then
|
||||
# use python 3.11 if available
|
||||
update-alternatives --install /usr/bin/python python /usr/bin/python3.11 1
|
||||
echo "# python calls python3.11"
|
||||
else
|
||||
echo "# FAIL- there is no tested version of python present"
|
||||
exit 1
|
||||
fi
|
||||
echo "# FAIL- there is no tested version of python present"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# make sure /usr/bin/pip exists (and calls pip3)
|
||||
update-alternatives --install /usr/bin/pip pip /usr/bin/pip3 1
|
||||
|
||||
# don't protect system packages from pip install
|
||||
# tracking issue: https://github.com/raspiblitz/raspiblitz/issues/4170
|
||||
for PYTHONDIR in /usr/lib/python3.*; do
|
||||
if [ -f "$PYTHONDIR/EXTERNALLY-MANAGED" ]; then
|
||||
rm "$PYTHONDIR/EXTERNALLY-MANAGED"
|
||||
fi
|
||||
done
|
||||
|
||||
# setuptools needed for Nyx
|
||||
pip install setuptools
|
||||
|
||||
|
|
@ -359,6 +346,8 @@ apt-get install -y dialog
|
|||
apt-get install -y qrencode
|
||||
# unzip for the pruned node snapshot
|
||||
apt-get install -y unzip
|
||||
# JoinMarket dependency https://github.com/JoinMarket-Org/joinmarket-clientserver/blob/5bfa08c6f558458c9a93e8095ce9dc1b62412838/install.sh#L76C10-L76C21
|
||||
apt-get install -y libltdl-dev
|
||||
apt-get clean
|
||||
apt-get -y autoremove
|
||||
|
||||
|
|
@ -400,21 +389,21 @@ if echo "${lastCommit}" | grep 13C688DB5B9C745DE4D2E4545BFB77609B081B65; then
|
|||
PGPsigner="openoms"
|
||||
PGPpubkeyLink="https://github.com/openoms.gpg"
|
||||
PGPpubkeyFingerprint="13C688DB5B9C745DE4D2E4545BFB77609B081B65"
|
||||
elif echo "${lastCommit}" | grep 4AEE18F83AFDEB23; then
|
||||
elif echo "${lastCommit}" | grep B5690EEEBB952194; then
|
||||
echo "# The last commit was made on GitHub and is signed with the GitHub PGP key."
|
||||
PGPsigner="web-flow"
|
||||
PGPpubkeyLink="https://github.com/${PGPsigner}.gpg"
|
||||
PGPpubkeyFingerprint="4AEE18F83AFDEB23"
|
||||
PGPpubkeyFingerprint="B5690EEEBB952194"
|
||||
else
|
||||
echo "# No known PGP key found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
command="sudo -u joinmarket bash /home/joinmarket/joininbox/scripts/verify.git.sh \
|
||||
command="bash /home/joinmarket/joininbox/scripts/verify.git.sh \
|
||||
${PGPsigner} ${PGPpubkeyLink} ${PGPpubkeyFingerprint}"
|
||||
echo "running: ${command}"
|
||||
chmod 777 /dev/shm
|
||||
${command} || exit 1
|
||||
sudo -u joinmarket ${command} || exit 1
|
||||
|
||||
runuser joinmarket -c "cp /home/joinmarket/joininbox/scripts/* /home/joinmarket/"
|
||||
runuser joinmarket -c "cp /home/joinmarket/joininbox/scripts/.* /home/joinmarket/ 2>/dev/null"
|
||||
|
|
@ -493,7 +482,7 @@ deb-src [arch=${arch}] https://deb.torproject.org/torproject.org ${distro} main"
|
|||
apt-get install -y build-essential fakeroot devscripts
|
||||
apt-get build-dep -y tor deb.torproject.org-keyring
|
||||
mkdir ~/debian-packages
|
||||
cd ~/debian-packages
|
||||
cd ~/debian-packages || exit 1
|
||||
apt-get source tor
|
||||
cd tor-* || exit 1
|
||||
debuild -rfakeroot -uc -us
|
||||
|
|
@ -541,6 +530,7 @@ echo
|
|||
apt-get install -y fail2ban ufw
|
||||
# autostart fail2ban
|
||||
systemctl enable fail2ban
|
||||
touch /var/log/auth.log
|
||||
|
||||
# set up the firewall
|
||||
ufw default deny incoming
|
||||
|
|
@ -593,7 +583,6 @@ echo "#############"
|
|||
echo "
|
||||
if [ -f \"/home/joinmarket/joinmarket-clientserver/jmvenv/bin/activate\" ]; then
|
||||
. /home/joinmarket/joinmarket-clientserver/jmvenv/bin/activate
|
||||
/home/joinmarket/joinmarket-clientserver/jmvenv/bin/python -c \"import PySide2\"
|
||||
cd /home/joinmarket/joinmarket-clientserver/scripts/
|
||||
fi
|
||||
# shortcut commands
|
||||
|
|
@ -616,10 +605,16 @@ echo "######################"
|
|||
echo "# Install JoinMarket"
|
||||
echo "######################"
|
||||
|
||||
qtgui=true
|
||||
|
||||
if [ "${cpu}" = x86_64 ]; then
|
||||
qtgui=true
|
||||
else
|
||||
# no qtgui on arm
|
||||
qtgui=false
|
||||
fi
|
||||
checkEntry=$(runuser joinmarket -c "cat /home/joinmarket/joinin.conf | grep -c qtgui")
|
||||
if [ ${checkEntry} -eq 0 ]; then
|
||||
echo "qtgui=true" | tee -a /home/joinmarket/joinin.conf
|
||||
echo "qtgui=$qtgui" | tee -a /home/joinmarket/joinin.conf
|
||||
fi
|
||||
if [ "$4" = "without-qt" ]; then
|
||||
qtgui="false"
|
||||
|
|
|
|||
120
ci/amd64/debian/build.amd64-debian.pkr.hcl
Normal file
120
ci/amd64/debian/build.amd64-debian.pkr.hcl
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
# images, checksums and signatures are at:
|
||||
# https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/
|
||||
# NOTE: This template is intended to be invoked via the wrapper script:
|
||||
# ci/amd64/packer.build.amd64-debian.sh
|
||||
# The wrapper resolves and injects the latest point-release ISO name and matching checksum
|
||||
# at runtime. Defaults below are placeholders and are not guaranteed to work if you run
|
||||
# `packer build` directly.
|
||||
variable "iso_name" { default = "debian-13-amd64-netinst.iso" }
|
||||
variable "iso_checksum" { default = "file:https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/SHA256SUMS" }
|
||||
|
||||
variable "github_user" { default = "openoms" }
|
||||
variable "branch" { default = "master" }
|
||||
|
||||
variable "boot" { default = "uefi" }
|
||||
variable "preseed_file" { default = "preseed.cfg" }
|
||||
variable "hostname" { default = "joininbox-amd64" }
|
||||
|
||||
variable "image_size" { default = "30000" }
|
||||
variable "image_type" { default = "qcow2" }
|
||||
|
||||
variable "memory" { default = "2048" }
|
||||
variable "cpus" { default = "2" }
|
||||
|
||||
locals {
|
||||
name_template = "joininbox-amd64-debian"
|
||||
image_extension = var.image_type == "raw" ? "img" : var.image_type
|
||||
bios_file = var.boot == "uefi" ? "OVMF.fd" : "bios-256k.bin"
|
||||
boot_command = var.boot == "uefi" ? [
|
||||
"<wait><wait><wait>c<wait><wait><wait>",
|
||||
"linux /install.amd/vmlinuz ",
|
||||
"auto=true ",
|
||||
"url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/${var.preseed_file} ",
|
||||
"hostname=${var.hostname} ",
|
||||
"domain=${var.hostname}.local ",
|
||||
"interface=auto ",
|
||||
"vga=788 noprompt quiet --<enter>",
|
||||
"initrd /install.amd/initrd.gz<enter>",
|
||||
"boot<enter>"
|
||||
] : [
|
||||
"<esc><wait>install <wait>",
|
||||
"<wait><wait><wait><wait><wait><wait><wait><wait><wait><wait><wait><wait><wait><wait><wait><wait> preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/${var.preseed_file} <wait>",
|
||||
"debian-installer=en_US.UTF-8 <wait>",
|
||||
"auto <wait>",
|
||||
"locale=en_US.UTF-8 <wait>",
|
||||
"kbd-chooser/method=us <wait>",
|
||||
"keyboard-configuration/xkb-keymap=us <wait>",
|
||||
"netcfg/get_hostname=${var.hostname} <wait>",
|
||||
"netcfg/get_domain=${var.hostname}.local <wait>",
|
||||
"fb=false <wait>",
|
||||
"debconf/frontend=noninteractive <wait>",
|
||||
"console-setup/ask_detect=false <wait>",
|
||||
"console-keymaps-at/keymap=us <wait>",
|
||||
"grub-installer/bootdev=default <wait>",
|
||||
"<enter><wait>"
|
||||
]
|
||||
}
|
||||
|
||||
source "qemu" "debian" {
|
||||
boot_command = local.boot_command
|
||||
boot_wait = "5s"
|
||||
cpus = var.cpus
|
||||
disk_size = var.image_size
|
||||
http_directory = "./http"
|
||||
iso_checksum = var.iso_checksum
|
||||
iso_url = "https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/${var.iso_name}"
|
||||
memory = var.memory
|
||||
output_directory = "../builds/${local.name_template}-qemu"
|
||||
shutdown_command = "echo 'joininbox' | sudo /sbin/shutdown -hP now"
|
||||
ssh_password = "joininbox"
|
||||
ssh_port = 22
|
||||
ssh_timeout = "10000s"
|
||||
ssh_username = "joinmarket"
|
||||
format = var.image_type
|
||||
vm_name = "${local.name_template}.${local.image_extension}"
|
||||
headless = false
|
||||
vnc_bind_address = "127.0.0.1"
|
||||
vnc_port_max = 5900
|
||||
vnc_port_min = 5900
|
||||
qemuargs = [
|
||||
["-m", var.memory],
|
||||
["-bios", local.bios_file],
|
||||
["-display", "none"]
|
||||
]
|
||||
}
|
||||
|
||||
build {
|
||||
description = "JoininBox amd64 Debian image build"
|
||||
sources = ["source.qemu.debian"]
|
||||
|
||||
provisioner "shell" {
|
||||
environment_vars = [
|
||||
"HOME_DIR=/home/joinmarket",
|
||||
"github_user=${var.github_user}",
|
||||
"branch=${var.branch}"
|
||||
]
|
||||
|
||||
execute_command = "echo 'joininbox' | {{.Vars}} sudo -S -E sh -eux '{{.Path}}'"
|
||||
expect_disconnect = true
|
||||
scripts = [
|
||||
"./scripts/update.sh",
|
||||
"./../_common/sshd.sh",
|
||||
"./scripts/networking.sh",
|
||||
"./scripts/sudoers.sh",
|
||||
"./scripts/systemd.sh",
|
||||
"./scripts/joininbox.sh",
|
||||
"./scripts/cleanup.sh"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
packer {
|
||||
required_version = ">= 1.7.0, < 2.0.0"
|
||||
|
||||
required_plugins {
|
||||
qemu = {
|
||||
source = "github.com/hashicorp/qemu"
|
||||
version = ">= 1.0.0, < 2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
choose-mirror-bin mirror/http/proxy string
|
||||
d-i apt-setup/use_mirror boolean true
|
||||
d-i base-installer/kernel/override-image string linux-server
|
||||
d-i clock-setup/utc boolean true
|
||||
d-i clock-setup/utc-auto boolean true
|
||||
d-i finish-install/reboot_in_progress note
|
||||
d-i grub-installer/only_debian boolean true
|
||||
d-i grub-installer/with_other_os boolean true
|
||||
d-i keymap select us
|
||||
d-i mirror/country string manual
|
||||
d-i mirror/http/directory string /debian
|
||||
d-i mirror/http/hostname string httpredir.debian.org
|
||||
d-i mirror/http/proxy string
|
||||
d-i partman-auto-lvm/guided_size string max
|
||||
d-i partman-auto/choose_recipe select atomic
|
||||
d-i partman-auto/method string lvm
|
||||
d-i partman-lvm/confirm boolean true
|
||||
d-i partman-lvm/confirm_nooverwrite boolean true
|
||||
d-i partman-lvm/device_remove_lvm boolean true
|
||||
d-i partman/choose_partition select finish
|
||||
d-i partman/confirm boolean true
|
||||
d-i partman/confirm_nooverwrite boolean true
|
||||
d-i partman/confirm_write_new_label boolean true
|
||||
d-i passwd/root-login boolean false
|
||||
d-i passwd/root-password-again password joininbox
|
||||
d-i passwd/root-password password joininbox
|
||||
d-i passwd/user-fullname string joinmarket
|
||||
d-i passwd/user-uid string 1000
|
||||
d-i passwd/user-password password joininbox
|
||||
d-i passwd/user-password-again password joininbox
|
||||
d-i passwd/username string joinmarket
|
||||
d-i pkgsel/include string sudo bzip2 acpid cryptsetup zlib1g-dev wget curl dkms fuse make nfs-common net-tools cifs-utils rsync
|
||||
d-i pkgsel/install-language-support boolean false
|
||||
d-i pkgsel/update-policy select none
|
||||
d-i pkgsel/upgrade select full-upgrade
|
||||
# Prevent packaged version of VirtualBox Guest Additions being installed:
|
||||
d-i preseed/early_command string sed -i \
|
||||
'/in-target/idiscover(){/sbin/discover|grep -v VirtualBox;}' \
|
||||
/usr/lib/pre-pkgsel.d/20install-hwpackages
|
||||
d-i time/zone string UTC
|
||||
d-i user-setup/allow-password-weak boolean true
|
||||
d-i user-setup/encrypt-home boolean false
|
||||
d-i preseed/late_command string sed -i '/^deb cdrom:/s/^/#/' /target/etc/apt/sources.list
|
||||
apt-cdrom-setup apt-setup/cdrom/set-first boolean false
|
||||
apt-mirror-setup apt-setup/use_mirror boolean true
|
||||
popularity-contest popularity-contest/participate boolean false
|
||||
tasksel tasksel/first multiselect standard, ssh-server
|
||||
72
ci/amd64/debian/http/preseed.cfg
Normal file
72
ci/amd64/debian/http/preseed.cfg
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
# https://github.com/chef/bento/blob/main/packer_templates/http/debian/preseed.cfg
|
||||
# https://www.debian.org/releases/stable/example-preseed.txt
|
||||
# https://github.com/tylert/packer-build/blob/master/source/debian/12_bookworm/base-uefi.preseed
|
||||
# variables: https://github.com/tylert/packer-build/blob/master/source/debian/12_bookworm/base-uefi.pkr.hcl
|
||||
|
||||
# Locale Setup
|
||||
d-i debian-installer/language string en
|
||||
d-i debian-installer/country string US
|
||||
d-i debian-installer/locale string en_US.UTF-8
|
||||
# d-i localechooser/supported-locales multiselect en_CA.UTF-8 fr_CA.UTF-8 zh_CN.UTF-8
|
||||
# d-i pkgsel/install-language-support boolean true
|
||||
|
||||
# Keyboard Setup
|
||||
d-i keyboard-configuration/xkb-keymap select us
|
||||
|
||||
# Clock Setup
|
||||
# d-i time/zone string Canada/Eastern
|
||||
d-i time/zone string UTC
|
||||
d-i clock-setup/utc boolean true
|
||||
# set above to false if making a bootable USB to run on same system as Windows
|
||||
|
||||
# Network Setup
|
||||
d-i netcfg/get_hostname string joininbox-amd64
|
||||
d-i netcfg/get_domain string
|
||||
# https://bugs.launchpad.net/ubuntu/+source/netcfg/+bug/713385
|
||||
d-i netcfg/choose_interface select auto
|
||||
# make sure you also add "interface=auto" to your boot command too
|
||||
# https://bugs.launchpad.net/ubuntu/+source/netcfg/+bug/713385
|
||||
|
||||
# User Setup
|
||||
d-i passwd/root-login boolean false
|
||||
d-i passwd/root-password-again password joininbox
|
||||
d-i passwd/root-password password joininbox
|
||||
d-i passwd/user-fullname string joinmarket
|
||||
d-i passwd/user-uid string 1000
|
||||
d-i passwd/user-password password joininbox
|
||||
d-i passwd/user-password-again password joininbox
|
||||
d-i passwd/username string joinmarket
|
||||
|
||||
# Package Setup
|
||||
d-i hw-detect/load_firmware boolean false
|
||||
d-i hw-detect/load_media boolean false
|
||||
apt-cdrom-setup apt-setup/cdrom/set-first boolean false
|
||||
d-i mirror/country string manual
|
||||
d-i mirror/http/hostname string httpredir.debian.org
|
||||
d-i mirror/http/directory string /debian
|
||||
d-i mirror/http/proxy string
|
||||
d-i apt-setup/contrib boolean true
|
||||
d-i apt-setup/non-free boolean true
|
||||
|
||||
tasksel tasksel/first multiselect ssh-server, standard
|
||||
d-i pkgsel/include string sudo bzip2 acpid cryptsetup zlib1g-dev wget curl dkms fuse make nfs-common net-tools cifs-utils rsync
|
||||
d-i pkgsel/install-language-support boolean false
|
||||
d-i pkgsel/update-policy select none
|
||||
d-i pkgsel/upgrade select full-upgrade
|
||||
|
||||
popularity-contest popularity-contest/participate boolean false
|
||||
|
||||
# Drive setup
|
||||
d-i partman-auto-lvm/guided_size string max
|
||||
d-i partman-auto/choose_recipe select atomic
|
||||
d-i partman-auto/method string lvm
|
||||
d-i partman-lvm/confirm boolean true
|
||||
d-i partman-lvm/confirm_nooverwrite boolean true
|
||||
d-i partman-lvm/device_remove_lvm boolean true
|
||||
d-i partman/choose_partition select finish
|
||||
d-i partman/confirm boolean true
|
||||
d-i partman/confirm_nooverwrite boolean true
|
||||
d-i partman/confirm_write_new_label boolean true
|
||||
|
||||
# Final Setup
|
||||
d-i finish-install/reboot_in_progress note
|
||||
|
|
@ -1,142 +0,0 @@
|
|||
{
|
||||
"variables": {
|
||||
"iso_name": "debian-12.2.0-amd64-netinst.iso",
|
||||
"iso_checksum": "23ab444503069d9ef681e3028016250289a33cc7bab079259b73100daee0af66",
|
||||
"box_basename": "debian",
|
||||
"build_directory": "../builds",
|
||||
"cpus": "2",
|
||||
"disk_size": "30000",
|
||||
"headless": "false",
|
||||
"http_directory": "{{template_dir}}/http",
|
||||
"memory": "2048",
|
||||
"mirror": "http://cdimage.debian.org/cdimage/release",
|
||||
"mirror_directory": "current/amd64/iso-cd",
|
||||
"name": "debian",
|
||||
"preseed_path": "debian-9/preseed.cfg",
|
||||
"qemu_display": "none",
|
||||
"qemu_bios": "bios-256k.bin",
|
||||
"template": "joininbox-amd64-debian",
|
||||
"boot_command": "<esc><wait>install <wait> preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/{{user `preseed_path`}} <wait>debian-installer=en_US.UTF-8 <wait>auto <wait>locale=en_US.UTF-8 <wait>kbd-chooser/method=us <wait>keyboard-configuration/xkb-keymap=us <wait>netcfg/get_hostname={{ .Name }} <wait>netcfg/get_domain=vagrantup.com <wait>fb=false <wait>debconf/frontend=noninteractive <wait>console-setup/ask_detect=false <wait>console-keymaps-at/keymap=us <wait>grub-installer/bootdev=default <wait><enter><wait>",
|
||||
"version": "TIMESTAMP"
|
||||
},
|
||||
"builders": [
|
||||
{
|
||||
"boot_command": "{{user `boot_command`}}",
|
||||
"boot_wait": "5s",
|
||||
"cpus": "{{ user `cpus` }}",
|
||||
"disk_size": "{{user `disk_size`}}",
|
||||
"headless": "{{ user `headless` }}",
|
||||
"http_directory": "{{user `http_directory`}}",
|
||||
"iso_checksum": "{{user `iso_checksum`}}",
|
||||
"iso_url": "{{user `mirror`}}/{{user `mirror_directory`}}/{{user `iso_name`}}",
|
||||
"memory": "{{ user `memory` }}",
|
||||
"output_directory": "{{ user `build_directory` }}/{{user `template`}}-qemu",
|
||||
"shutdown_command": "echo 'joininbox' | sudo /sbin/shutdown -hP now",
|
||||
"ssh_password": "joininbox",
|
||||
"ssh_port": 22,
|
||||
"ssh_timeout": "10000s",
|
||||
"ssh_username": "joinmarket",
|
||||
"type": "qemu",
|
||||
"format": "qcow2",
|
||||
"vm_name": "{{ user `template` }}.qcow2",
|
||||
"qemuargs": [
|
||||
[ "-m", "{{ user `memory` }}" ],
|
||||
[ "-bios", "{{ user `qemu_bios` }}" ],
|
||||
[ "-display", "{{ user `qemu_display` }}" ]
|
||||
]
|
||||
},
|
||||
{
|
||||
"boot_command": "{{user `boot_command`}}",
|
||||
"boot_wait": "5s",
|
||||
"cpus": "{{ user `cpus` }}",
|
||||
"disk_size": "{{user `disk_size`}}",
|
||||
"guest_os_type": "Debian_64",
|
||||
"hard_drive_interface": "sata",
|
||||
"headless": "{{ user `headless` }}",
|
||||
"http_directory": "{{user `http_directory`}}",
|
||||
"iso_checksum": "{{user `iso_checksum`}}",
|
||||
"iso_url": "{{user `mirror`}}/{{user `mirror_directory`}}/{{user `iso_name`}}",
|
||||
"memory": "{{ user `memory` }}",
|
||||
"output_directory": "{{ user `build_directory` }}/packer-{{user `template`}}-virtualbox",
|
||||
"shutdown_command": "echo 'joininbox' | sudo -S /sbin/shutdown -hP now",
|
||||
"ssh_password": "joininbox",
|
||||
"ssh_port": 22,
|
||||
"ssh_timeout": "10000s",
|
||||
"ssh_username": "joinmarket",
|
||||
"type": "virtualbox-iso",
|
||||
"virtualbox_version_file": ".vbox_version",
|
||||
"vm_name": "{{ user `template` }}"
|
||||
},
|
||||
{
|
||||
"boot_command": "{{user `boot_command`}}",
|
||||
"boot_wait": "5s",
|
||||
"cpus": "{{ user `cpus` }}",
|
||||
"disk_size": "{{user `disk_size`}}",
|
||||
"guest_os_type": "debian8-64",
|
||||
"headless": "{{ user `headless` }}",
|
||||
"http_directory": "{{user `http_directory`}}",
|
||||
"iso_checksum": "{{user `iso_checksum`}}",
|
||||
"iso_url": "{{user `mirror`}}/{{user `mirror_directory`}}/{{user `iso_name`}}",
|
||||
"memory": "{{ user `memory` }}",
|
||||
"output_directory": "{{ user `build_directory` }}/packer-{{user `template`}}-vmware",
|
||||
"shutdown_command": "echo 'joininbox' | sudo -S /sbin/shutdown -hP now",
|
||||
"ssh_password": "joininbox",
|
||||
"ssh_port": 22,
|
||||
"ssh_timeout": "10000s",
|
||||
"ssh_username": "joinmarket",
|
||||
"tools_upload_flavor": "linux",
|
||||
"type": "vmware-iso",
|
||||
"vm_name": "{{ user `template` }}",
|
||||
"vmx_data": {
|
||||
"cpuid.coresPerSocket": "1",
|
||||
"ethernet0.pciSlotNumber": "32"
|
||||
},
|
||||
"vmx_remove_ethernet_interfaces": true
|
||||
},
|
||||
{
|
||||
"boot_command": "{{user `boot_command`}}",
|
||||
"boot_wait": "5s",
|
||||
"cpus": "{{ user `cpus` }}",
|
||||
"disk_size": "{{user `disk_size`}}",
|
||||
"guest_os_type": "debian",
|
||||
"http_directory": "{{user `http_directory`}}",
|
||||
"iso_checksum": "{{user `iso_checksum`}}",
|
||||
"iso_url": "{{user `mirror`}}/{{user `mirror_directory`}}/{{user `iso_name`}}",
|
||||
"memory": "{{ user `memory` }}",
|
||||
"output_directory": "{{ user `build_directory` }}/packer-{{user `template`}}-parallels",
|
||||
"parallels_tools_flavor": "lin",
|
||||
"prlctl_version_file": ".prlctl_version",
|
||||
"shutdown_command": "echo 'joininbox' | sudo -S /sbin/shutdown -hP now",
|
||||
"ssh_password": "joininbox",
|
||||
"ssh_port": 22,
|
||||
"ssh_timeout": "10000s",
|
||||
"ssh_username": "joinmarket",
|
||||
"type": "parallels-iso",
|
||||
"vm_name": "{{ user `template` }}"
|
||||
}
|
||||
],
|
||||
"provisioners": [
|
||||
{
|
||||
"type": "shell",
|
||||
"environment_vars": [
|
||||
"HOME_DIR=/home/joinmarket",
|
||||
"http_proxy={{user `http_proxy`}}",
|
||||
"https_proxy={{user `https_proxy`}}",
|
||||
"no_proxy={{user `no_proxy`}}",
|
||||
"github_user={{user `github_user`}}",
|
||||
"branch={{user `branch`}}"
|
||||
],
|
||||
"execute_command": "echo 'joininbox' | {{.Vars}} sudo -S -E sh -eux '{{.Path}}'",
|
||||
"expect_disconnect": true,
|
||||
"scripts": [
|
||||
"{{template_dir}}/scripts/update.sh",
|
||||
"{{template_dir}}/../_common/sshd.sh",
|
||||
"{{template_dir}}/scripts/networking.sh",
|
||||
"{{template_dir}}/scripts/sudoers.sh",
|
||||
"{{template_dir}}/scripts/systemd.sh",
|
||||
"{{template_dir}}/scripts/joininbox.sh",
|
||||
"{{template_dir}}/scripts/cleanup.sh"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -7,3 +7,6 @@ update-grub;
|
|||
|
||||
# Adding a 2 sec delay to the interface up, to make the dhclient happy
|
||||
echo "pre-up sleep 2" >> /etc/network/interfaces
|
||||
|
||||
echo "$(hostname -I | awk '{print $1}') $(hostname)" >>/etc/hosts
|
||||
echo "127.0.1.1 $(hostname)" >>/etc/hosts
|
||||
|
|
|
|||
|
|
@ -1,36 +1,135 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
sudo apt-get update
|
||||
|
||||
# install packer
|
||||
if ! packer version 2>/dev/null; then
|
||||
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
|
||||
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
|
||||
sudo apt-get update
|
||||
echo -e "\nInstalling packer..."
|
||||
sudo apt-get install -y packer
|
||||
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
|
||||
sudo apt-add-repository -y "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
|
||||
sudo apt-get update
|
||||
echo -e "\nInstalling packer..."
|
||||
sudo apt-get install -y packer
|
||||
else
|
||||
echo "# Packer is installed"
|
||||
echo "# Packer is installed"
|
||||
fi
|
||||
|
||||
# Install qemu
|
||||
# install qemu and UEFI firmware
|
||||
echo "# Install qemu ..."
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y qemu-system
|
||||
sudo apt-get install -y qemu-system ovmf
|
||||
|
||||
# set vars from positional arguments (for backward compatibility with CI)
|
||||
if [ $# -gt 0 ]; then
|
||||
github_user=$1
|
||||
github_user=$1
|
||||
else
|
||||
github_user=openoms
|
||||
github_user=openoms
|
||||
fi
|
||||
|
||||
if [ $# -gt 1 ]; then
|
||||
branch=$2
|
||||
branch=$2
|
||||
else
|
||||
branch=master
|
||||
branch=master
|
||||
fi
|
||||
|
||||
# Resolve latest Debian 13 amd64 netinst ISO from SHA256SUMS.
|
||||
# This avoids 404s and checksum mismatches when Debian point releases rotate.
|
||||
debian_major=${DEBIAN_MAJOR:-13}
|
||||
debian_iso_dir="https://cdimage.debian.org/debian-cd/current/amd64/iso-cd"
|
||||
debian_sums_url="${debian_iso_dir}/SHA256SUMS"
|
||||
debian_sums_sig_url="${debian_iso_dir}/SHA256SUMS.sign"
|
||||
debian_cd_key_urls=(
|
||||
"https://www.debian.org/CD/key-DA87E80D6294BE9B.txt"
|
||||
"https://www.debian.org/CD/key-988021A964E6EA7D.txt"
|
||||
)
|
||||
debian_cd_expected_fprs=(
|
||||
"DF9B9C49EAA9298432589D76DA87E80D6294BE9B"
|
||||
"10460DAD76165AD81FBC0CE9988021A964E6EA7D"
|
||||
)
|
||||
|
||||
if ! command -v gpgv >/dev/null 2>&1; then
|
||||
echo "# Installing gpgv"
|
||||
sudo apt-get install -y gpgv
|
||||
fi
|
||||
|
||||
if ! command -v gpgv >/dev/null 2>&1; then
|
||||
echo "ERROR: gpgv is required for signature verification"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
tmp_checksums_dir=$(mktemp -d)
|
||||
trap 'rm -rf "${tmp_checksums_dir}"' EXIT
|
||||
|
||||
echo "# Downloading checksum files"
|
||||
curl -fsSL "${debian_sums_url}" -o "${tmp_checksums_dir}/SHA256SUMS"
|
||||
curl -fsSL "${debian_sums_sig_url}" -o "${tmp_checksums_dir}/SHA256SUMS.sign"
|
||||
|
||||
echo "# Verifying SHA256SUMS signature (PGP)"
|
||||
cd_keyring="${tmp_checksums_dir}/debian-cd-signing-keys.gpg"
|
||||
tmp_gnupg_home="${tmp_checksums_dir}/gnupg-home"
|
||||
mkdir -p "${tmp_gnupg_home}"
|
||||
chmod 700 "${tmp_gnupg_home}"
|
||||
|
||||
for i in "${!debian_cd_key_urls[@]}"; do
|
||||
key_url="${debian_cd_key_urls[$i]}"
|
||||
expected_fpr="${debian_cd_expected_fprs[$i]}"
|
||||
key_file="${tmp_checksums_dir}/cd-key-${i}.asc"
|
||||
curl -fsSL "${key_url}" -o "${key_file}"
|
||||
actual_fpr=$(gpg --homedir "${tmp_gnupg_home}" --show-keys --with-colons "${key_file}" 2>/dev/null | awk -F: '/^fpr:/ {print $10; exit}')
|
||||
if [ -z "${actual_fpr}" ] || [ "${actual_fpr}" != "${expected_fpr}" ]; then
|
||||
echo "# SHA256SUMS signature: FAIL"
|
||||
echo "ERROR: Unexpected fingerprint for ${key_url}"
|
||||
exit 1
|
||||
fi
|
||||
gpg --homedir "${tmp_gnupg_home}" --no-default-keyring --keyring "${cd_keyring}" --import "${key_file}" >/dev/null 2>&1
|
||||
done
|
||||
|
||||
if gpgv --keyring "${cd_keyring}" "${tmp_checksums_dir}/SHA256SUMS.sign" "${tmp_checksums_dir}/SHA256SUMS" >/dev/null 2>&1; then
|
||||
echo "# SHA256SUMS signature: PASS"
|
||||
else
|
||||
echo "# SHA256SUMS signature: FAIL"
|
||||
echo "ERROR: PGP signature verification failed for ${debian_sums_url}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "# Resolving latest Debian ${debian_major} amd64 netinst ISO from ${debian_sums_url}"
|
||||
latest_iso_line=$(awk -v major="${debian_major}" '$2 ~ ("^\\*?\\.?/?debian-" major "\\.[0-9]+\\.[0-9]+-amd64-netinst\\.iso$") {print $1 " " $2}' "${tmp_checksums_dir}/SHA256SUMS" | \
|
||||
sort -k2 -V | tail -1)
|
||||
|
||||
if [ -z "${latest_iso_line}" ]; then
|
||||
echo "ERROR: Could not resolve latest Debian ${debian_major} amd64 netinst ISO from ${debian_sums_url}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
latest_iso_checksum=$(echo "${latest_iso_line}" | awk '{print $1}')
|
||||
latest_iso_name=$(echo "${latest_iso_line}" | awk '{print $2}' | sed 's#^\*##; s#^\./##; s#^/##')
|
||||
|
||||
if [ -z "${latest_iso_name}" ] || [ -z "${latest_iso_checksum}" ]; then
|
||||
echo "ERROR: Failed parsing ISO name/checksum from: ${latest_iso_line}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
resolved_checksum=$(awk -v iso="${latest_iso_name}" '($2 == iso || $2 == "*" iso || $2 == "./" iso || $2 == "/" iso) {print $1; exit}' "${tmp_checksums_dir}/SHA256SUMS")
|
||||
if [ -z "${resolved_checksum}" ]; then
|
||||
echo "ERROR: Could not find checksum entry for ${latest_iso_name} in ${debian_sums_url}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "# Debian ISO selection"
|
||||
echo "# ISO filename : ${latest_iso_name}"
|
||||
echo "# SHA256 (selected) : ${latest_iso_checksum}"
|
||||
echo "# SHA256 (resolved) : ${resolved_checksum}"
|
||||
if [ "${latest_iso_checksum}" = "${resolved_checksum}" ]; then
|
||||
echo "# Checksum verify : PASS"
|
||||
else
|
||||
echo "# Checksum verify : FAIL"
|
||||
echo "ERROR: Checksum mismatch for ${latest_iso_name}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
vars="-var github_user=${github_user} -var branch=${branch} -var iso_name=${latest_iso_name} -var iso_checksum=${latest_iso_checksum}"
|
||||
|
||||
# Build the image
|
||||
echo "# Building image ..."
|
||||
echo "# Build the image with: github_user=${github_user} branch=${branch}"
|
||||
cd debian
|
||||
PACKER_LOG=1 packer build \
|
||||
-var github_user=${github_user} -var branch=${branch} \
|
||||
-only=qemu joininbox-amd64-debian.json
|
||||
packer init -upgrade .
|
||||
PACKER_LOG=1 packer build ${vars} -only=qemu.debian build.amd64-debian.pkr.hcl || exit 1
|
||||
|
|
|
|||
138
ci/amd64/test.amd64-image-bats.sh
Executable file
138
ci/amd64/test.amd64-image-bats.sh
Executable file
|
|
@ -0,0 +1,138 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
image="${1:-${GITHUB_WORKSPACE:-$(pwd)}/ci/amd64/builds/joininbox-amd64-debian-qemu/joininbox-amd64-debian.qcow2}"
|
||||
ssh_port="${SSH_PORT:-2222}"
|
||||
ssh_password="${SSH_PASSWORD:-joininbox}"
|
||||
qemu_pid_file="${RUNNER_TEMP:-/tmp}/joininbox-qemu.pid"
|
||||
bats_core_dir="${BATS_CORE_DIR:-${GITHUB_WORKSPACE:-$(pwd)}/.bats-core}"
|
||||
|
||||
if [ ! -f "${image}" ]; then
|
||||
echo "Missing image: ${image}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -x "${bats_core_dir}/bin/bats" ]; then
|
||||
echo "Missing bats-core checkout: ${bats_core_dir}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y ovmf qemu-system-x86 sshpass
|
||||
|
||||
ssh_opts=(
|
||||
-o StrictHostKeyChecking=no
|
||||
-o UserKnownHostsFile=/dev/null
|
||||
-o ConnectTimeout=5
|
||||
-p "${ssh_port}"
|
||||
)
|
||||
|
||||
ovmf_code="${OVMF_CODE:-${OVMF_BIOS:-}}"
|
||||
ovmf_vars_template="${OVMF_VARS:-}"
|
||||
ovmf_vars="${RUNNER_TEMP:-/tmp}/joininbox-ovmf-vars.fd"
|
||||
qemu_firmware_args=()
|
||||
|
||||
if [ -z "${ovmf_code}" ]; then
|
||||
for candidate in \
|
||||
/usr/share/OVMF/OVMF_CODE_4M.fd \
|
||||
/usr/share/OVMF/OVMF_CODE_4M.secboot.fd \
|
||||
/usr/share/OVMF/OVMF_CODE_4M.ms.fd \
|
||||
/usr/share/OVMF/OVMF_CODE.fd \
|
||||
/usr/share/OVMF/OVMF.fd \
|
||||
/usr/share/ovmf/OVMF_CODE_4M.fd \
|
||||
/usr/share/ovmf/OVMF_CODE_4M.secboot.fd \
|
||||
/usr/share/ovmf/OVMF_CODE_4M.ms.fd \
|
||||
/usr/share/ovmf/OVMF_CODE.fd \
|
||||
/usr/share/ovmf/OVMF.fd \
|
||||
OVMF.fd; do
|
||||
if [ -f "${candidate}" ]; then
|
||||
ovmf_code="${candidate}"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ -z "${ovmf_code}" ] || [ ! -f "${ovmf_code}" ]; then
|
||||
echo "No OVMF firmware found. Set OVMF_CODE or OVMF_BIOS to the firmware path." >&2
|
||||
find /usr/share/OVMF /usr/share/ovmf -maxdepth 1 -type f -name '*.fd' -print 2>/dev/null || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "${ovmf_code##*/}" in
|
||||
*CODE*)
|
||||
if [ -z "${ovmf_vars_template}" ]; then
|
||||
for candidate in \
|
||||
"${ovmf_code/CODE/VARS}" \
|
||||
/usr/share/OVMF/OVMF_VARS_4M.fd \
|
||||
/usr/share/OVMF/OVMF_VARS.fd \
|
||||
/usr/share/ovmf/OVMF_VARS_4M.fd \
|
||||
/usr/share/ovmf/OVMF_VARS.fd; do
|
||||
if [ -f "${candidate}" ]; then
|
||||
ovmf_vars_template="${candidate}"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ -z "${ovmf_vars_template}" ] || [ ! -f "${ovmf_vars_template}" ]; then
|
||||
echo "No OVMF VARS template found for ${ovmf_code}. Set OVMF_VARS to the template path." >&2
|
||||
find /usr/share/OVMF /usr/share/ovmf -maxdepth 1 -type f -name '*.fd' -print 2>/dev/null || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cp "${ovmf_vars_template}" "${ovmf_vars}"
|
||||
qemu_firmware_args=(
|
||||
-drive "if=pflash,format=raw,readonly=on,file=${ovmf_code}"
|
||||
-drive "if=pflash,format=raw,file=${ovmf_vars}"
|
||||
)
|
||||
;;
|
||||
*)
|
||||
qemu_firmware_args=(-bios "${ovmf_code}")
|
||||
;;
|
||||
esac
|
||||
|
||||
cleanup() {
|
||||
if [ -f "${qemu_pid_file}" ]; then
|
||||
qemu_pid="$(cat "${qemu_pid_file}")"
|
||||
if kill -0 "${qemu_pid}" 2>/dev/null; then
|
||||
kill "${qemu_pid}" 2>/dev/null || true
|
||||
timeout 30s tail --pid="${qemu_pid}" -f /dev/null 2>/dev/null ||
|
||||
kill -9 "${qemu_pid}" 2>/dev/null ||
|
||||
true
|
||||
fi
|
||||
fi
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
rm -f "${qemu_pid_file}"
|
||||
|
||||
qemu-system-x86_64 \
|
||||
-m 2048 \
|
||||
-smp 2 \
|
||||
"${qemu_firmware_args[@]}" \
|
||||
-drive "file=${image},format=qcow2" \
|
||||
-netdev "user,id=net0,hostfwd=tcp:127.0.0.1:${ssh_port}-:22" \
|
||||
-device e1000,netdev=net0 \
|
||||
-display none \
|
||||
-snapshot \
|
||||
-pidfile "${qemu_pid_file}" \
|
||||
-daemonize
|
||||
|
||||
echo "Waiting for SSH in the booted image"
|
||||
for attempt in {1..120}; do
|
||||
if sshpass -p "${ssh_password}" ssh "${ssh_opts[@]}" joinmarket@127.0.0.1 "true" 2>/dev/null; then
|
||||
break
|
||||
fi
|
||||
if [ "${attempt}" -eq 120 ]; then
|
||||
echo "Timed out waiting for SSH" >&2
|
||||
exit 1
|
||||
fi
|
||||
sleep 5
|
||||
done
|
||||
|
||||
tar -C "${bats_core_dir}" -cf - . |
|
||||
sshpass -p "${ssh_password}" ssh "${ssh_opts[@]}" joinmarket@127.0.0.1 \
|
||||
"mkdir -p /tmp/bats-core && tar -C /tmp/bats-core -xf -"
|
||||
|
||||
sshpass -p "${ssh_password}" ssh "${ssh_opts[@]}" joinmarket@127.0.0.1 \
|
||||
"PATH=/tmp/bats-core/bin:\$PATH /home/joinmarket/joininbox/test/run-bats-local.sh"
|
||||
|
|
@ -3,10 +3,10 @@ variable "branch" {}
|
|||
|
||||
source "arm" "joininbox-arm64-rpi" {
|
||||
file_checksum_type = "sha256"
|
||||
file_checksum = "a68cd2bfe7831c438d8a5d832803ae0db17afec9f3cd370d9e8748c7b5456283"
|
||||
file_checksum = "62d025b9bc7ca0e1facfec74ae56ac13978b6745c58177f081d39fbb8041ed45"
|
||||
file_target_extension = "xz"
|
||||
file_unarchive_cmd = ["xz", "--decompress", "$ARCHIVE_PATH"]
|
||||
file_urls = ["https://raspi.debian.net/tested/20230612_raspi_4_bookworm.img.xz"]
|
||||
file_urls = ["https://downloads.raspberrypi.com/raspios_lite_arm64/images/raspios_lite_arm64-2025-05-13/2025-05-13-raspios-bookworm-arm64-lite.img.xz"]
|
||||
image_build_method = "resize"
|
||||
image_chroot_env = ["PATH=/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin"]
|
||||
image_partitions {
|
||||
|
|
@ -39,7 +39,8 @@ build {
|
|||
inline = [
|
||||
"echo 'nameserver 1.1.1.1' >/etc/resolv.conf",
|
||||
"echo 'nameserver 8.8.8.8' >>/etc/resolv.conf",
|
||||
"echo $(hostname -I | awk '{print $1}') $(hostname) >>/etc/hosts",
|
||||
"echo $(hostname -I | awk '{print $1}') $(hostname) >>/etc/hosts",
|
||||
"echo 127.0.1.1 $(hostname) >>/etc/hosts",
|
||||
"echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections",
|
||||
"apt-get update",
|
||||
"apt-get install -y sudo wget",
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ Since the RaspiBlitz v1.6 run this script:
|
|||
To set up manually:
|
||||
|
||||
* Edit the bitcoin.conf:
|
||||
`$ sudo nano /mnt/hdd/bitcoin/bitcoin.conf`
|
||||
`$ sudo nano /mnt/hdd/app-data/bitcoin/bitcoin.conf`
|
||||
|
||||
* Change the disablewallet option to 0:
|
||||
```
|
||||
|
|
@ -40,12 +40,12 @@ In the terminal of the node - allow remote RPC connections to Bitcoin Core
|
|||
This can be skipped if you [connect through Tor](#tor-connection)
|
||||
|
||||
1) Edit the bitcoin.conf
|
||||
`$ sudo nano /mnt/hdd/bitcoin/bitcoin.conf`
|
||||
`$ sudo nano /mnt/hdd/app-data/bitcoin/bitcoin.conf`
|
||||
|
||||
Add the values:
|
||||
* `rpcallowip=JOININBOX_IP` or `RANGE`
|
||||
* either specify the LAN IP of the computer (here JoininBox)
|
||||
* or use a range like: `192.168.1.0/24` - edit to your local subnet - the first 3 numbes of the LAN IP address, the example used here is: 192.168.1.x
|
||||
* or use a range like: `192.168.1.0/24` - edit to your local subnet - the first 3 numbers of the LAN IP address, the example used here is: 192.168.1.x
|
||||
* `rpcbind=LAN_IP_OF_THE_NODE`
|
||||
* use the local IP of the bitcoin node in the example: `192.168.1.4`
|
||||
* can keep the other `rpcallowip` and `rpcbind` entries especially for the localhost: `127.0.0.1`
|
||||
|
|
@ -109,8 +109,8 @@ Fill in the `Tor_Hidden_Service.onion` to the `rpc_host` in the `joinmarket.cfg`
|
|||
|
||||
### CONFIG -> CONNECT in JoininBox
|
||||
* Username: `raspibolt `
|
||||
* Password: `passwordB` or `sudo cat /mnt/hdd/bitcoin/bitcoin.conf | grep rpcpassword | cut -c 13-`
|
||||
* Host: `LAN_IP_OF_THE_NODE` or `sudo cat /mnt/hdd/tor/bitcoinrpc/hostname`
|
||||
* Password: `passwordB` or `sudo cat /mnt/hdd/bitcoin/app-data/bitcoin.conf | grep rpcpassword | cut -c 13-`
|
||||
* Host: `LAN_IP_OF_THE_NODE` or `sudo cat /mnt/hdd/app-data/tor/bitcoinrpc/hostname`
|
||||
* Port: `8332`
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ dialog_color = (CYAN,BLACK,OFF)
|
|||
title_color = (CYAN,BLACK,ON)
|
||||
|
||||
# Dialog box border color
|
||||
border_color = (BLACK,BLACK,ON)
|
||||
border_color = (CYAN,BLACK,ON)
|
||||
|
||||
# Active button color
|
||||
button_active_color = (BLACK,CYAN,ON)
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ function torthistx() {
|
|||
# command: stats
|
||||
# shows the uptime and the fees earned as a Maker
|
||||
function stats() {
|
||||
/home/joinmarket/info.stats.sh
|
||||
/home/joinmarket/info.stats.sh showAllEarned
|
||||
}
|
||||
|
||||
# command: qtgui
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ joininConfPath="/home/joinmarket/joinin.conf"
|
|||
function downloadBitcoinCore() {
|
||||
# set version
|
||||
# https://bitcoincore.org/en/download/
|
||||
bitcoinVersion="25.0"
|
||||
bitcoinVersion="29.2"
|
||||
|
||||
if bitcoin-cli --version | grep $bitcoinVersion >/dev/null; then
|
||||
echo "# Bitcoin Core $bitcoinVersion is already installed"
|
||||
|
|
@ -39,7 +39,7 @@ function downloadBitcoinCore() {
|
|||
echo
|
||||
else
|
||||
echo
|
||||
echo "# BUILD FAILED --> the PGP verification failed / signature(${goodSignature}) "
|
||||
echo "# BUILD FAILED --> the PGP verification failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
|
@ -155,25 +155,44 @@ function installSignet() {
|
|||
Description=Bitcoin daemon on signet
|
||||
|
||||
[Service]
|
||||
Environment='MALLOC_ARENA_MAX=1'
|
||||
PIDFile=/home/joinmarket/bitcoin/bitcoind.pid
|
||||
ExecStart=/home/joinmarket/bitcoin/bitcoind -signet -daemon \\
|
||||
-datadir=/home/joinmarket/.bitcoin \\
|
||||
-conf=/home/joinmarket/.bitcoin/bitcoin.conf \\
|
||||
-pid=/home/joinmarket/bitcoin/bitcoind.pid
|
||||
PermissionsStartOnly=true
|
||||
|
||||
# Process management
|
||||
####################
|
||||
Type=forking
|
||||
Restart=on-failure
|
||||
TimeoutStartSec=infinity
|
||||
TimeoutStopSec=600
|
||||
|
||||
# Directory creation and permissions
|
||||
####################################
|
||||
# Run as joinmarket:joinmarket
|
||||
User=joinmarket
|
||||
Group=joinmarket
|
||||
Type=forking
|
||||
PIDFile=/home/joinmarket/bitcoin/bitcoind.pid
|
||||
ExecStart=/home/joinmarket/bitcoin/bitcoind -signet -daemon \
|
||||
-datadir=/home/joinmarket/.bitcoin \
|
||||
-conf=/home/joinmarket/.bitcoin/bitcoin.conf \
|
||||
-pid=/home/joinmarket/bitcoin/bitcoind.pid
|
||||
Restart=always
|
||||
TimeoutSec=120
|
||||
RestartSec=30
|
||||
|
||||
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
|
||||
|
|
@ -228,8 +247,8 @@ setJMconfigToSignet() {
|
|||
sed -i "s/^rpc_password =.*/rpc_password = $RPCPWSIGNET/g" $JMcfgPath
|
||||
echo "# rpc_password = $RPCPWSIGNET"
|
||||
# rpc_wallet_file
|
||||
sed -i "s/^rpc_wallet_file =.*/rpc_wallet_file = wallet.dat/g" $JMcfgPath
|
||||
echo "# using the bitcoind wallet: wallet.dat"
|
||||
sed -i "s/^rpc_wallet_file =.*/rpc_wallet_file = watch-only-descriptor-wallet/g" $JMcfgPath
|
||||
echo "# using the bitcoind watch-only-descriptor-wallet"
|
||||
# rpc_host
|
||||
sed -i "s/^rpc_host =.*/rpc_host = 127.0.0.1/g" $JMcfgPath
|
||||
echo "# rpc_host = 127.0.0.1"
|
||||
|
|
@ -302,20 +321,79 @@ function getRPC {
|
|||
fi
|
||||
}
|
||||
|
||||
# getConnectedBitcoinCoreVersion - read the numeric version over node RPC
|
||||
function getConnectedBitcoinCoreVersion {
|
||||
local tor=""
|
||||
if [ "$(echo "$rpc_host" | grep -c .onion)" -gt 0 ]; then
|
||||
tor="torsocks"
|
||||
fi
|
||||
$tor curl -sS --data-binary \
|
||||
'{"jsonrpc": "1.0", "id":"get_bitcoin_core_version", "method": "getnetworkinfo", "params": []}' \
|
||||
"http://$rpc_user:$rpc_pass@$rpc_host:$rpc_port/" 2>/dev/null |
|
||||
jq -r '.result.version // empty' 2>/dev/null
|
||||
}
|
||||
|
||||
# migrateLegacyRPCWalletConfig - switch the persisted JoinMarket RPC wallet
|
||||
# from the legacy wallet.dat name to the descriptor wallet used by JoininBox
|
||||
# when the connected Bitcoin Core version is v30.0 or newer
|
||||
function migrateLegacyRPCWalletConfig {
|
||||
if [ "$rpc_wallet" != "wallet.dat" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
local bitcoinCoreVersion
|
||||
bitcoinCoreVersion=$(getConnectedBitcoinCoreVersion)
|
||||
if ! [[ "$bitcoinCoreVersion" =~ ^[0-9]+$ ]]; then
|
||||
echo "# Could not determine the connected Bitcoin Core version; keeping wallet.dat"
|
||||
return 0
|
||||
fi
|
||||
# Bitcoin Core's numeric version is 290200 for v29.2 and 300000 for v30.0.
|
||||
if [ "$bitcoinCoreVersion" -lt 300000 ]; then
|
||||
echo "# Connected Bitcoin Core is v29.x or earlier; keeping wallet.dat"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "# Migrating the configured Bitcoin Core wallet from wallet.dat to watch-only-descriptor-wallet"
|
||||
local migrationConfigOutput
|
||||
if ! migrationConfigOutput=$(mktemp "${JMcfgPath}.XXXXXX"); then
|
||||
echo "# Failed to create a temporary descriptor wallet configuration" >&2
|
||||
return 1
|
||||
fi
|
||||
if ! sed \
|
||||
"s/^rpc_wallet_file =.*/rpc_wallet_file = watch-only-descriptor-wallet/g" \
|
||||
"$JMcfgPath" >"$migrationConfigOutput"; then
|
||||
rm -f "$migrationConfigOutput"
|
||||
echo "# Failed to prepare the descriptor wallet configuration" >&2
|
||||
return 1
|
||||
fi
|
||||
if ! mv "$migrationConfigOutput" "$JMcfgPath"; then
|
||||
rm -f "$migrationConfigOutput"
|
||||
echo "# Failed to update the descriptor wallet configuration" >&2
|
||||
return 1
|
||||
fi
|
||||
getRPC
|
||||
if [ "$rpc_wallet" != "watch-only-descriptor-wallet" ]; then
|
||||
echo "# Failed to select the descriptor wallet configuration" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# checkRPCwallet <wallet>
|
||||
function checkRPCwallet {
|
||||
getRPC
|
||||
migrateLegacyRPCWalletConfig || return 1
|
||||
if [ $# -eq 0 ]; then
|
||||
rpc_wallet=$rpc_wallet
|
||||
else
|
||||
rpc_wallet=$1
|
||||
fi
|
||||
|
||||
echo "# Making sure the set $rpc_wallet wallet is present in bitcoind"
|
||||
trap 'rm -f "$connectionOutput"' EXIT
|
||||
connectionOutput=$(mktemp -p /dev/shm/)
|
||||
walletFound=$(customRPC "# Check wallet" "listwallets" 2>$connectionOutput | grep -c "$rpc_wallet")
|
||||
if [ $walletFound -eq 0 ]; then
|
||||
echo "# Setting a watch only wallet in Bitcoin Core named $rpc_wallet"
|
||||
echo "# Setting a watch-only-descriptor-wallet in Bitcoin Core named $rpc_wallet"
|
||||
tor=""
|
||||
if [ $(echo $rpc_host | grep -c .onion) -gt 0 ]; then
|
||||
tor="torsocks"
|
||||
|
|
@ -324,8 +402,8 @@ function checkRPCwallet {
|
|||
fi
|
||||
#TODO rewrite customRPC to support multiple params
|
||||
$tor curl -sS --data-binary \
|
||||
'{"jsonrpc": "1.0", "id":"# Create the bitcoind wallet", "method": "createwallet", "params": {"wallet_name":"'"$rpc_wallet"'","descriptors":false}}' \
|
||||
http://$rpc_user:$rpc_pass@$rpc_host:$rpc_port/wallet/$rpc_wallet | jq .
|
||||
'{"jsonrpc": "1.0", "id":"# Create the bitcoind wallet", "method": "createwallet", "params": {"wallet_name":"'"$rpc_wallet"'","descriptors":true,"disable_private_keys":true}}' \
|
||||
http://$rpc_user:$rpc_pass@$rpc_host:$rpc_port/ | jq .
|
||||
echo
|
||||
walletFound=$(customRPC "# Check wallet" "listwallets" 2>$connectionOutput | grep -c "$rpc_wallet")
|
||||
if [ $walletFound -eq 0 ]; then
|
||||
|
|
@ -337,6 +415,75 @@ function checkRPCwallet {
|
|||
echo
|
||||
fi
|
||||
echo "# The wallet: $rpc_wallet is present and loaded in the connected bitcoind"
|
||||
|
||||
# Check for wallet migration from legacy wallet.dat
|
||||
checkWalletMigration
|
||||
}
|
||||
|
||||
# checkWalletMigration - detects legacy wallet.dat and guides user through migration
|
||||
# This function checks if:
|
||||
# 1. The old wallet.dat exists in Bitcoin Core
|
||||
# 2. The new watch-only-descriptor-wallet is being used
|
||||
# 3. Migration has not been completed yet
|
||||
# If migration is needed, it prompts the user to rescan after opening their JM wallets
|
||||
function checkWalletMigration {
|
||||
# Skip if migration was already completed
|
||||
if grep -q "walletMigrationDone=true" "${joininConfPath}" 2>/dev/null; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Skip if we're not using the new descriptor wallet
|
||||
if [ "$rpc_wallet" != "watch-only-descriptor-wallet" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# RPC settings are already available from parent checkRPCwallet function
|
||||
tor=""
|
||||
if [ "$(echo "$rpc_host" | grep -c .onion)" -gt 0 ]; then
|
||||
tor="torsocks"
|
||||
fi
|
||||
|
||||
# Check if old wallet.dat exists in bitcoind (try to load it to see if it exists)
|
||||
# First check listwalletdir for wallet.dat
|
||||
oldWalletExists=$($tor curl -sS --data-binary \
|
||||
'{"jsonrpc": "1.0", "id":"check_old_wallet", "method": "listwalletdir", "params": []}' \
|
||||
"http://$rpc_user:$rpc_pass@$rpc_host:$rpc_port/" 2>/dev/null | jq -r '.result.wallets[].name' 2>/dev/null | grep -c "^wallet.dat$")
|
||||
|
||||
if [ "$oldWalletExists" -gt 0 ]; then
|
||||
echo
|
||||
echo "########################################################################"
|
||||
echo "# WALLET MIGRATION NOTICE"
|
||||
echo "########################################################################"
|
||||
echo
|
||||
echo "# A legacy wallet.dat was detected in Bitcoin Core."
|
||||
echo "# JoininBox now uses descriptor wallets (watch-only-descriptor-wallet)"
|
||||
echo "# for better compatibility with modern Bitcoin Core versions."
|
||||
echo
|
||||
echo "# To complete the migration and see your transaction history:"
|
||||
echo
|
||||
echo "# 1. Open each of your JoinMarket wallets once using:"
|
||||
echo "# WALLET -> DISPLAY"
|
||||
echo "# This imports the addresses into the new descriptor wallet."
|
||||
echo
|
||||
echo "# 2. After opening all wallets, run a blockchain rescan:"
|
||||
echo "# WALLET -> RESCAN"
|
||||
echo "# Use blockheight 481824 (first SegWit block) or later if you know when your wallet had its first deposit."
|
||||
echo
|
||||
echo "# The rescan may take several hours depending on wallet age."
|
||||
echo "# You can monitor progress in the Bitcoin Core debug.log"
|
||||
echo
|
||||
echo "########################################################################"
|
||||
echo
|
||||
echo "# Press ENTER to continue..."
|
||||
read -r
|
||||
|
||||
# Mark migration notice as shown (user can still run rescan manually)
|
||||
if ! grep -q "walletMigrationDone=" "${joininConfPath}" 2>/dev/null; then
|
||||
echo "walletMigrationDone=true" >>"${joininConfPath}"
|
||||
else
|
||||
sed -i "s/^walletMigrationDone=.*/walletMigrationDone=true/g" "${joininConfPath}"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# customRPC - sends a custom RPC command
|
||||
|
|
@ -398,10 +545,16 @@ function connectLocalNode() {
|
|||
elif [ "${network}" = testnet ]; then
|
||||
rpc_port="18332"
|
||||
fi
|
||||
rpc_wallet="wallet.dat"
|
||||
rpc_wallet="watch-only-descriptor-wallet"
|
||||
if [ $runningEnv = raspiblitz ]; then
|
||||
rpc_user=$(sudo cat /mnt/hdd/bitcoin/bitcoin.conf | grep rpcuser | cut -c 9-)
|
||||
rpc_pass=$(sudo cat /mnt/hdd/bitcoin/bitcoin.conf | grep rpcpassword | cut -c 13-)
|
||||
if [ -f "/mnt/hdd/raspiblitz.conf" ]; then
|
||||
rpc_user=$(sudo cat /mnt/hdd/bitcoin/bitcoin.conf | grep rpcuser | cut -c 9-)
|
||||
rpc_pass=$(sudo cat /mnt/hdd/bitcoin/bitcoin.conf | grep rpcpassword | cut -c 13-)
|
||||
else
|
||||
rpc_user=$(sudo cat /mnt/hdd/app-data/bitcoin/bitcoin.conf | grep rpcuser | cut -c 9-)
|
||||
rpc_pass=$(sudo cat /mnt/hdd/app-data/bitcoin/bitcoin.conf | grep rpcpassword | cut -c 13-)
|
||||
fi
|
||||
|
||||
elif [ $runningEnv = mynode ]; then
|
||||
rpc_user=mynode
|
||||
rpc_pass=$(sudo cat /mnt/hdd/mynode/settings/.btcrpcpw)
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ function menu_MAKER() {
|
|||
sleep 3
|
||||
dialog \
|
||||
--title "Monitoring the Yield Generator - press CTRL+C to exit" \
|
||||
--prgbox "sudo journalctl -fn20 -u yg-privacyenhanced" 30 200
|
||||
--prgbox "sudo journalctl -fn100 -u yg-privacyenhanced" -1 -1
|
||||
echo "# returning to the menu..."
|
||||
sleep 1
|
||||
/home/joinmarket/menu.yg.sh
|
||||
|
|
|
|||
|
|
@ -7,12 +7,21 @@ currentJBcommit=$(cd /home/joinmarket/joininbox; git describe --tags)
|
|||
currentJBtag=$(cd /home/joinmarket/joininbox; git tag | sort -V | tail -1)
|
||||
currentJMversion=$(cd /home/joinmarket/joinmarket-clientserver 2>/dev/null; \
|
||||
git describe --tags 2>/dev/null)
|
||||
currentBTCversion=$(bitcoind --version | grep version)
|
||||
|
||||
# paths
|
||||
walletPath="/home/joinmarket/.joinmarket/wallets/"
|
||||
JMcfgPath="/home/joinmarket/.joinmarket/joinmarket.cfg"
|
||||
joininConfPath="/home/joinmarket/joinin.conf"
|
||||
|
||||
## dialog fixes
|
||||
# fallback for unknown terminal types (e.g., xterm-ghostty)
|
||||
if ! infocmp "$TERM" &>/dev/null; then
|
||||
export TERM=xterm-256color
|
||||
fi
|
||||
# fix dialog box drawing characters
|
||||
export NCURSES_NO_UTF8_ACS=1
|
||||
|
||||
# functions
|
||||
source /home/joinmarket/_functions.menu.sh
|
||||
source /home/joinmarket/_functions.bitcoincore.sh
|
||||
|
|
@ -22,7 +31,6 @@ fi
|
|||
|
||||
function activateJMvenv() {
|
||||
. /home/joinmarket/joinmarket-clientserver/jmvenv/bin/activate || exit 1
|
||||
/home/joinmarket/joinmarket-clientserver/jmvenv/bin/python -c "import PySide2"
|
||||
}
|
||||
|
||||
function openMenuIfCancelled() {
|
||||
|
|
@ -162,16 +170,16 @@ function stopYG() {
|
|||
|
||||
function YGnickname() {
|
||||
# Retrieves nickname from the latest NickServ message in the newest logfile
|
||||
if ls -td /home/joinmarket/.joinmarket/logs/* 1>&2>/dev/null ; then
|
||||
newest_log=$(ls -td /home/joinmarket/.joinmarket/logs/* | grep J5 | head -n 1)
|
||||
name=$(grep NickServ $newest_log | tail -1 | awk '{print $9}')
|
||||
if [ ${#name} -eq 0 ];then
|
||||
newest_log=$(ls -td /home/joinmarket/.joinmarket/logs/*J5* 2>/dev/null | head -n 1)
|
||||
if [ -n "$newest_log" ] && [ -f "$newest_log" ]; then
|
||||
name=$(grep NickServ "$newest_log" 2>/dev/null | tail -1 | awk '{print $9}')
|
||||
if [ ${#name} -eq 0 ]; then
|
||||
name="no_Nick_see_LOGS"
|
||||
fi
|
||||
else
|
||||
name="waiting__to__run"
|
||||
fi
|
||||
echo $name
|
||||
echo "$name"
|
||||
}
|
||||
|
||||
# copyJoininboxScripts
|
||||
|
|
@ -249,28 +257,33 @@ function generateJMconfig() {
|
|||
|
||||
setJMconfigToSignet
|
||||
|
||||
elif [ -f "/mnt/hdd/bitcoin/bitcoin.conf" ]; then
|
||||
elif [ $runningEnv = "raspiblitz" ]; then
|
||||
echo
|
||||
echo "## editing the joinmarket.cfg with the local bitcoin RPC settings."
|
||||
|
||||
RPCUSER=$(sudo cat /mnt/hdd/bitcoin/bitcoin.conf | grep rpcuser | cut -c 9-)
|
||||
sed -i "s/^rpc_user =.*/rpc_user = $RPCUSER/g" $JMcfgPath
|
||||
echo "# rpc_user = $RPCUSER"
|
||||
|
||||
PASSWORD_B=$(sudo cat /mnt/hdd/bitcoin/bitcoin.conf | grep rpcpassword | cut -c 13-)
|
||||
sed -i "s/^rpc_password =.*/rpc_password = $PASSWORD_B/g" $JMcfgPath
|
||||
echo "# rpc_password = $PASSWORD_B"
|
||||
|
||||
RPCPORT=$(sudo cat /mnt/hdd/bitcoin/bitcoin.conf | grep main.rpcport | cut -c 14-)
|
||||
if [ ${#RPCPORT} -eq 0 ];then
|
||||
if [ -f "/mnt/hdd/bitcoin/bitcoin.conf" ]; then
|
||||
RPCUSER=$(sudo cat /mnt/hdd/bitcoin/bitcoin.conf | grep rpcuser | cut -c 9-)
|
||||
sed -i "s/^rpc_user =.*/rpc_user = $RPCUSER/g" $JMcfgPath
|
||||
echo "# rpc_user = $RPCUSER"
|
||||
PASSWORD_B=$(sudo cat /mnt/hdd/bitcoin/bitcoin.conf | grep rpcpassword | cut -c 13-)
|
||||
sed -i "s/^rpc_password =.*/rpc_password = $PASSWORD_B/g" $JMcfgPath
|
||||
echo "# rpc_password = $PASSWORD_B"
|
||||
RPCPORT=$(sudo cat /mnt/hdd/bitcoin/bitcoin.conf | grep main.rpcport | cut -c 14-)
|
||||
else
|
||||
RPCUSER=$(sudo cat /mnt/hdd/app-data/bitcoin/bitcoin.conf | grep rpcuser | cut -c 9-)
|
||||
sed -i "s/^rpc_user =.*/rpc_user = $RPCUSER/g" $JMcfgPath
|
||||
echo "# rpc_user = $RPCUSER"
|
||||
PASSWORD_B=$(sudo cat /mnt/hdd/app-data/bitcoin/bitcoin.conf | grep rpcpassword | cut -c 13-)
|
||||
sed -i "s/^rpc_password =.*/rpc_password = $PASSWORD_B/g" $JMcfgPath
|
||||
echo "# rpc_password = $PASSWORD_B"
|
||||
RPCPORT=$(sudo cat /mnt/hdd/app-data/bitcoin/bitcoin.conf | grep main.rpcport | cut -c 14-)
|
||||
fi
|
||||
if [ ${#RPCPORT} -eq 0 ]; then
|
||||
RPCPORT=8332
|
||||
fi
|
||||
sed -i "s/^rpc_port =.*/rpc_port = $RPCPORT/g" $JMcfgPath
|
||||
echo "# rpc_port = $RPCPORT"
|
||||
|
||||
sed -i "s/^rpc_wallet_file =.*/rpc_wallet_file = wallet.dat/g" $JMcfgPath
|
||||
echo "# using the bitcoind wallet: wallet.dat"
|
||||
|
||||
sed -i "s/^rpc_wallet_file =.*/rpc_wallet_file = watch-only-descriptor-wallet/g" $JMcfgPath
|
||||
echo "# using the bitcoind watch-only-descriptor-wallet"
|
||||
# set joinin.conf value
|
||||
/home/joinmarket/set.value.sh set network mainnet ${joininConfPath}
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ Instructions to COPY wallets from another computer
|
|||
You can use the wallets from another JoinMarket instance
|
||||
"
|
||||
if [ "${CHOICE}" = "LAN" ]; then
|
||||
if [ -f "/mnt/hdd/raspiblitz.conf" ] ; then
|
||||
if [ -f "/mnt/hdd/raspiblitz.conf" ] || [ -f "/mnt/hdd/app-data/raspiblitz.conf" ] ; then
|
||||
echo "Both computers (the RaspiBlitz and the source computer with the wallet(s))"
|
||||
else
|
||||
echo "Both computers (the JoininBox and the source computer with the wallet(s))"
|
||||
|
|
@ -62,9 +62,9 @@ elif [ "${CHOICE}" = "TOR" ]; then
|
|||
echo "torsocks scp ./*.jmdat joinmarket@${TOR_ADDRESS}:~/.joinmarket/wallets/"
|
||||
fi
|
||||
echo ""
|
||||
if [ -f "/mnt/hdd/raspiblitz.conf" ] ; then
|
||||
if [ -f "/mnt/hdd/raspiblitz.conf" ] || [ -f "/mnt/hdd/app-data/raspiblitz.conf" ] ; then
|
||||
echo "Use the PASSWORD_B to authorize the file transfer
|
||||
(same as the rpcpassword in the /mnt/hdd/bitcoin/bitcoin.conf)."
|
||||
(same as the rpcpassword in the bitcoin.conf)."
|
||||
else
|
||||
echo "This command will ask for the SSH PASSWORD of the JoininBox."
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@ source /home/joinmarket/_functions.sh
|
|||
|
||||
# check connectedRemoteNode var in joinin.conf
|
||||
if ! grep -Eq "^connectedRemoteNode=" $joininConfPath; then
|
||||
echo "connectedRemoteNode=off" >> $joininConfPath
|
||||
echo "connectedRemoteNode=off" >>$joininConfPath
|
||||
fi
|
||||
|
||||
if [ "$1" = "signetOn" ]; then
|
||||
installBitcoinCore
|
||||
installSignet
|
||||
if [ "$connectedRemoteNode" = "on" ];then
|
||||
if [ "$connectedRemoteNode" = "on" ]; then
|
||||
backupJMconf
|
||||
fi
|
||||
generateJMconfig
|
||||
|
|
@ -24,16 +24,16 @@ if [ "$1" = "signetOn" ]; then
|
|||
bitcoinUser="joinmarket"
|
||||
cliPath="/home/joinmarket/bitcoin/"
|
||||
fi
|
||||
if [ ! -f /home/${bitcoinUser}/.bitcoin/signet/wallets/wallet.dat/wallet.dat ];then
|
||||
echo "# Create wallet.dat for signet ..."
|
||||
if [ ! -d /home/${bitcoinUser}/.bitcoin/signet/wallets/watch-only-descriptor-wallet ]; then
|
||||
echo "# Create watch-only-descriptor-wallet for signet ..."
|
||||
sleep 10
|
||||
sudo -u ${bitcoinUser} ${cliPath}/bitcoin-cli -signet -named createwallet wallet_name=wallet.dat descriptors=false
|
||||
sudo -u ${bitcoinUser} ${cliPath}/bitcoin-cli -signet -named createwallet wallet_name=watch-only-descriptor-wallet descriptors=true disable_private_keys=true
|
||||
fi
|
||||
|
||||
elif [ "$1" = "signetOff" ]; then
|
||||
removeSignetdService
|
||||
isSignet=$(grep -c "network = signet" < $JMcfgPath)
|
||||
if [ $isSignet -gt 0 ];then
|
||||
isSignet=$(grep -c "network = signet" <$JMcfgPath)
|
||||
if [ $isSignet -gt 0 ]; then
|
||||
echo "# Removing the joinmarket.cfg with signet settings"
|
||||
rm -f $JMcfgPath
|
||||
else
|
||||
|
|
|
|||
|
|
@ -1,14 +1,21 @@
|
|||
#!/bin/bash
|
||||
|
||||
testedJMversion="v0.9.10"
|
||||
# https://github.com/JoinMarket-Org/joinmarket-clientserver/releases
|
||||
# Use tag for verification when available, otherwise use commit hash
|
||||
testedJMversion="v0.9.12"
|
||||
|
||||
PGPsigner="kristapsk"
|
||||
PGPpkeys="https://github.com/kristapsk.gpg"
|
||||
PGPcheck="33E472FE870C7E5D"
|
||||
# https://github.com/JoinMarket-Org/joinmarket-clientserver/commits/master/
|
||||
# Only used if testedJMversion is empty or not set
|
||||
#testedJMcommit="ce32bafbb5d716bde61830f71266410249d43dbc"
|
||||
|
||||
#PGPsigner="waxwing"
|
||||
#PGPpkeys="https://raw.githubusercontent.com/JoinMarket-Org/joinmarket-clientserver/master/pubkeys/AdamGibson.asc"
|
||||
#PGPcheck="2B6FC204D9BF332D062B461A141001A1AF77F20B"
|
||||
PGPsigner="AdamISZ"
|
||||
PGPpkeys="https://github.com/AdamISZ.gpg"
|
||||
# AdamISZ current primary code-signing key used for v0.9.12
|
||||
PGPcheck="0F1C7345D9193D1C8E3F21810C44134F93234873"
|
||||
|
||||
#PGPsigner="kristapsk"
|
||||
#PGPpkeys="https://github.com/kristapsk.gpg"
|
||||
#PGPcheck="33E472FE870C7E5D"
|
||||
|
||||
me="${0##/*}"
|
||||
|
||||
|
|
@ -20,13 +27,13 @@ usage() {
|
|||
printf %s"${me} [--option <argument>]
|
||||
|
||||
a script to install, update or configure JoinMarket
|
||||
the latest tested version: $testedJMversion is installed by default with the QT GUI
|
||||
the latest tested version: ${testedJMversion:-$testedJMcommit} is installed by default with the QT GUI
|
||||
|
||||
Options:
|
||||
-h, --help this help info
|
||||
-i, --install [install|config|update|testPR|commit] install options, use 'commit' for the latest master
|
||||
-v, --version [version|number-of-PR] the version to install or PR to test (default: ${testedJMversion})
|
||||
-q, --qtgui [0|1] install the QT GUI and dependencies (default: 1)
|
||||
-q, --qtgui [0|1] install the QT GUI and dependencies (default: 0)
|
||||
-u, --user [user] the linux user to install with (default: joinmarket)
|
||||
|
||||
Notes:
|
||||
|
|
@ -109,10 +116,13 @@ done
|
|||
: "${install:=install}"
|
||||
range_argument install "install" "config" "update" "testPR" "commit"
|
||||
|
||||
: "${version:=${testedJMversion}}"
|
||||
curl -s "https://github.com/JoinMarket-Org/joinmarket-clientserver/release/tag/${version}" | grep -q "\"message\": \"Version not found\"" && error_msg "'There is no: https://github.com/JoinMarket-Org/joinmarket-clientserver/release/tag/${version}'"
|
||||
|
||||
: "${qtgui:=true}"
|
||||
# Use tag if set, otherwise use commit hash
|
||||
: "${version:=${testedJMversion:-$testedJMcommit}}"
|
||||
# Only check GitHub releases if version looks like a tag (starts with 'v')
|
||||
if [[ "${version}" == v* ]]; then
|
||||
curl -s "https://github.com/JoinMarket-Org/joinmarket-clientserver/releases/tag/${version}" | grep -q "\"message\": \"Version not found\"" && error_msg "'There is no: https://github.com/JoinMarket-Org/joinmarket-clientserver/releases/tag/${version}'"
|
||||
fi
|
||||
: "${qtgui:=false}"
|
||||
range_argument qtgui "0" "1" "false" "true"
|
||||
|
||||
: "${user:=joinmarket}"
|
||||
|
|
@ -140,7 +150,6 @@ if [ "${user}" != "joinmarket" ]; then
|
|||
echo "
|
||||
if [ -f \"/home/${user}/joinmarket-clientserver/jmvenv/bin/activate\" ]; then
|
||||
. /home/${user}/joinmarket-clientserver/jmvenv/bin/activate
|
||||
/home/${user}/joinmarket-clientserver/jmvenv/bin/python -c \"import PySide2\"
|
||||
cd /home/${user}/joinmarket-clientserver/scripts/
|
||||
fi
|
||||
" | sudo -u ${user} tee -a /home/${user}/.bashrc
|
||||
|
|
@ -152,22 +161,14 @@ checkEntry=$(sudo -u ${user} cat /home/${user}/joinin.conf | grep -c "qtgui")
|
|||
if [ ${checkEntry} -eq 0 ]; then
|
||||
echo "qtgui=true" | sudo -u ${user} tee -a /home/${user}/joinin.conf
|
||||
fi
|
||||
if [ "${qtgui}" = "false" ]; then
|
||||
sudo -u ${user} sed -i "s/^qtgui=.*/qtgui=false/g" /home/${user}/joinin.conf
|
||||
fi
|
||||
sudo -u ${user} sed -i "s/^qtgui=.*/qtgui=${qtgui}/g" /home/${user}/joinin.conf
|
||||
|
||||
# installJoinMarket [update|testPR <PRnumber>|commit]
|
||||
function installJoinMarket() {
|
||||
cpu=$(uname -m)
|
||||
cd /home/${user} || exit 1
|
||||
if [ "${qtgui}" = "true" ]; then
|
||||
# PySide2 for armf: https://packages.debian.org/buster/python3-pyside2.qtcore
|
||||
echo "# Installing ARM specific dependencies to run the QT GUI"
|
||||
sudo apt-get install -y python3-pyside2.qtcore python3-pyside2.qtgui \
|
||||
python3-pyside2.qtwidgets zlib1g-dev libjpeg-dev python3-pyqt5 libltdl-dev
|
||||
fi
|
||||
# https://github.com/JoinMarket-Org/joinmarket-clientserver/issues/668#issuecomment-717815719
|
||||
sudo apt-get install -y build-essential automake pkg-config libffi-dev python3-dev
|
||||
sudo -u ${user} pip config set global.break-system-packages true
|
||||
sudo -u ${user} pip install libtool asn1crypto cffi pycparser
|
||||
echo "# Installing JoinMarket"
|
||||
|
||||
|
|
@ -191,37 +192,29 @@ function installJoinMarket() {
|
|||
elif [ "$install" = "update" ] && [ ${#2} -gt 0 ]; then
|
||||
updateVersion="$2"
|
||||
sudo -u ${user} git reset --hard $updateVersion
|
||||
else
|
||||
sudo -u ${user} git reset --hard $testedJMversion
|
||||
|
||||
sudo -u ${user} wget --prefer-family=ipv4 -O "pgp_keys.asc" ${PGPpkeys}
|
||||
sudo -u ${user} gpg --import --import-options show-only ./pgp_keys.asc
|
||||
fingerprint=$(sudo -u ${user} gpg "pgp_keys.asc" 2>/dev/null | grep "${PGPcheck}" -c)
|
||||
if [ ${fingerprint} -lt 1 ]; then
|
||||
echo
|
||||
echo "# WARNING --> the PGP fingerprint is not as expected for ${PGPsigner}"
|
||||
echo "# Should contain PGP: ${PGPcheck}"
|
||||
echo "# PRESS ENTER to TAKE THE RISK if you think all is OK"
|
||||
read key
|
||||
fi
|
||||
sudo -u ${user} gpg --import ./pgp_keys.asc
|
||||
|
||||
verifyResult=$(sudo -u ${user} git verify-tag $testedJMversion 2>&1)
|
||||
|
||||
goodSignature=$(echo ${verifyResult} | grep 'Good signature' -c)
|
||||
echo "# goodSignature(${goodSignature})"
|
||||
correctKey=$(echo ${verifyResult} | tr -d " \t\n\r" | grep "${PGPcheck}" -c)
|
||||
echo "# correctKey(${correctKey})"
|
||||
if [ ${correctKey} -lt 1 ] || [ ${goodSignature} -lt 1 ]; then
|
||||
echo
|
||||
echo "# BUILD FAILED --> PGP verification not OK / signature(${goodSignature}) verify(${correctKey})"
|
||||
exit 1
|
||||
echo "# Verifying signature for version: $updateVersion"
|
||||
# Determine if it's a tag (starts with 'v') or commit hash
|
||||
if [[ "$updateVersion" == v* ]]; then
|
||||
sudo -u ${user} bash /home/joinmarket/joininbox/scripts/verify.git.sh \
|
||||
"${PGPsigner}" "${PGPpkeys}" "${PGPcheck}" "$updateVersion" || exit 1
|
||||
else
|
||||
echo
|
||||
echo "#########################################################"
|
||||
echo "# OK --> the PGP signature of the $testedJMversion tag is correct"
|
||||
echo "#########################################################"
|
||||
echo
|
||||
sudo -u ${user} bash /home/joinmarket/joininbox/scripts/verify.git.sh \
|
||||
"${PGPsigner}" "${PGPpkeys}" "${PGPcheck}" || exit 1
|
||||
fi
|
||||
else
|
||||
# Decide whether to use tag or commit
|
||||
if [ -n "${testedJMversion}" ]; then
|
||||
echo "# Installing tested version: ${testedJMversion}"
|
||||
sudo -u ${user} git reset --hard $testedJMversion
|
||||
echo "# Verifying tag signature: ${testedJMversion}"
|
||||
sudo -u ${user} bash /home/joinmarket/joininbox/scripts/verify.git.sh \
|
||||
"${PGPsigner}" "${PGPpkeys}" "${PGPcheck}" "${testedJMversion}" || exit 1
|
||||
else
|
||||
echo "# Installing tested commit: ${testedJMcommit}"
|
||||
sudo -u ${user} git reset --hard $testedJMcommit
|
||||
echo "# Verifying commit signature: ${testedJMcommit}"
|
||||
sudo -u ${user} bash /home/joinmarket/joininbox/scripts/verify.git.sh \
|
||||
"${PGPsigner}" "${PGPpkeys}" "${PGPcheck}" || exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
|
|
@ -232,30 +225,6 @@ function installJoinMarket() {
|
|||
fi
|
||||
# do not clear screen during installation
|
||||
sudo -u ${user} sed -i 's/clear//g' install.sh
|
||||
# do not stop at installing Debian dependencies
|
||||
sudo -u ${user} sed -i \
|
||||
"s#^ if ! sudo apt-get install \${deb_deps\[@\]}; then#\
|
||||
if ! sudo apt-get install -y \${deb_deps\[@\]}; then#g" install.sh
|
||||
|
||||
if [ ${cpu} != "x86_64" ]; then
|
||||
echo "# Make install.sh set up jmvenv with -- system-site-packages on arm"
|
||||
# and import the PySide2 armf package from the system
|
||||
sudo -u ${user} sed -i "s#^ virtualenv -p \"\${python}\" \"\${jm_source}/jmvenv\" || return 1#\
|
||||
virtualenv --system-site-packages -p \"\${python}\" \"\${jm_source}/jmvenv\" || return 1 ;\
|
||||
/home/${user}/joinmarket-clientserver/jmvenv/bin/python -c \'import PySide2\'\
|
||||
#g" install.sh
|
||||
# don't install PySide2 - using the system-site-package instead
|
||||
sudo -u ${user} sed -i "s#^PySide2.*##g" requirements/gui.txt
|
||||
# don't install PyQt5 - using the system package instead
|
||||
sudo -u ${user} sed -i "s#^PyQt5.*##g" requirements/gui.txt
|
||||
sudo -u ${user} sed -i "s#PyQt5!=5.15.0,!=5.15.1,!=5.15.2,!=6.0##g" jmqtui/setup.py
|
||||
fi
|
||||
|
||||
# pin werkzeug dependency to 2.2.0 as in:
|
||||
# https://github.com/JoinMarket-Org/joinmarket-clientserver/pull/1485/files
|
||||
if ! grep 'werkzeug==' jmclient/setup.py; then
|
||||
sed -i "s/autobahn==20.12.3/&', 'werkzeug==2.2.0/g" jmclient/setup.py
|
||||
fi
|
||||
|
||||
if [ "${qtgui}" = "false" ]; then
|
||||
GUIchoice="--without-qt"
|
||||
|
|
|
|||
|
|
@ -1,33 +1,38 @@
|
|||
# Install Jam and connect to a remote Joininbox
|
||||
|
||||
* tested on Debian Bullseye desktop - Ubuntu should also work
|
||||
* tested on Debian Bullseye and Bookworm desktop - Ubuntu should also work
|
||||
|
||||
### Download the repo
|
||||
```
|
||||
git clone https://github.com/openoms/joininbox
|
||||
cd joininbox
|
||||
```
|
||||
|
||||
### Install Jam locally
|
||||
* will be under the user: `jam`
|
||||
```
|
||||
cd scripts/jam-remote
|
||||
bash install.jam.sh on
|
||||
```
|
||||
|
||||
### On your Joininbox
|
||||
## Steps in your Joininbox terminal
|
||||
* (optional) update the joininbox scripts: `UPDATE` - `ADVANCED` - `JBCOMMIT`
|
||||
* start the `API` from `TOOLS`
|
||||
* (optional) start the ob-watcher from `OFFERS`
|
||||
|
||||
## Steps on your desktop
|
||||
### Download the repo
|
||||
* move to a directory where the joininbox repo will be stored
|
||||
```
|
||||
git clone https://github.com/openoms/joininbox
|
||||
cd joininbox
|
||||
```
|
||||
|
||||
### Install Jam locally
|
||||
* will be under the user: `jam`
|
||||
```
|
||||
cd scripts/jam-remote
|
||||
bash install.jam.sh on
|
||||
```
|
||||
|
||||
### Forward the API and ob-watcher ports with ssh from your Joininbox
|
||||
```
|
||||
bash ssh-portforward $JOININBOX_LAN_IP
|
||||
```
|
||||
* run the ssh-port-forward script in the `joininbox/scripts/jam-remote` folder
|
||||
```
|
||||
bash ./ssh-port-forward.sh $JOININBOX_LAN_IP
|
||||
```
|
||||
* leave this terminal open until working with Jam
|
||||
* close when done to close the ssh connection
|
||||
* Earn will continue to run on the Joininbox
|
||||
* can check it's logs in the menu - `MAKER` - `LOGS`
|
||||
|
||||
### Open Jam locally using the wallets on your remote Joininbox
|
||||
`https://localhost:7501`
|
||||
* open Jam at https://localhost:7501
|
||||
* accept the self-signed certificate served from your Joininbox
|
||||
* Use Jam - docs: https://jamdocs.org/
|
||||
* Earn will continue to run on the Joininbox even after the terminal and Jam windows are closed
|
||||
* can check the logs in the Joininbox menu - `MAKER` - `LOGS`
|
||||
|
|
|
|||
|
|
@ -3,15 +3,15 @@
|
|||
# https://github.com/joinmarket-webui/jam
|
||||
|
||||
USERNAME=jam
|
||||
WEBUI_VERSION="v0.1.6"
|
||||
WEBUI_VERSION="v0.4.0"
|
||||
REPO=joinmarket-webui/jam
|
||||
HOME_DIR=/home/${USERNAME}
|
||||
APP_DIR=webui
|
||||
SOURCEDIR=$(pwd)
|
||||
|
||||
PGPsigner="dergigi"
|
||||
PGPsigner="theborakompanioni"
|
||||
PGPpubkeyLink="https://github.com/${PGPsigner}.gpg"
|
||||
PGPpubkeyFingerprint="89C4A25E69A5DE7F"
|
||||
PGPpubkeyFingerprint="E8070AF0053AAC0D"
|
||||
|
||||
# command info
|
||||
if [ $# -eq 0 ] || [ "$1" = "-h" ] || [ "$1" = "-help" ]; then
|
||||
|
|
@ -59,8 +59,8 @@ if [ "$1" = "on" ]; then
|
|||
cd jam || exit 1
|
||||
sudo -u $USERNAME git reset --hard ${WEBUI_VERSION}
|
||||
|
||||
#sudo -u $USERNAME bash ${SOURCEDIR}/../verify.git.sh \
|
||||
# "${PGPsigner}" "${PGPpubkeyLink}" "${PGPpubkeyFingerprint}" "v${WEBUI_VERSION}" || exit 1
|
||||
sudo -u $USERNAME bash ${SOURCEDIR}/../verify.git.sh \
|
||||
"${PGPsigner}" "${PGPpubkeyLink}" "${PGPpubkeyFingerprint}" "${WEBUI_VERSION}" || exit 1
|
||||
|
||||
cd $HOME_DIR || exit 1
|
||||
sudo -u $USERNAME mv jam $APP_DIR
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@
|
|||
|
||||
USERNAME=jam
|
||||
|
||||
sudo apt install nginx
|
||||
sudo apt-get install -y nginx
|
||||
|
||||
if ! sudo ls /home/jam/nginx/tls.cert || ! sudo ls /home/jam/nginx/tls.key; then
|
||||
sudo apt-get install openssl
|
||||
sudo apt-get install -y openssl
|
||||
|
||||
subj="/C=US/ST=Utah/L=Lehi/O=Your Company, Inc./OU=IT/CN=example.com"
|
||||
sudo -u $USERNAME mkdir -p /home/jam/nginx/ \
|
||||
|
|
|
|||
|
|
@ -10,7 +10,11 @@ if [ ${#network} -eq 0 ] || [ "${network}" = "unknown" ] ;then
|
|||
elif [ "${runningEnv}" = mynode ];then
|
||||
network=mainnet
|
||||
elif [ "${runningEnv}" = raspiblitz ];then
|
||||
source /mnt/hdd/raspiblitz.conf
|
||||
if [ -f "/mnt/hdd/raspiblitz.conf" ]; then
|
||||
source /mnt/hdd/raspiblitz.conf
|
||||
else
|
||||
source /mnt/hdd/app-data/raspiblitz.conf
|
||||
fi
|
||||
if [ $network = bitcoin ];then
|
||||
network=${chain}net
|
||||
else
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
#!/bin/bash
|
||||
|
||||
source /home/joinmarket/joinin.conf
|
||||
source /mnt/hdd/raspiblitz.conf
|
||||
if [ -f "/mnt/hdd/raspiblitz.conf" ]; then
|
||||
source /mnt/hdd/raspiblitz.conf
|
||||
else
|
||||
source /mnt/hdd/app-data/raspiblitz.conf
|
||||
fi
|
||||
|
||||
# BASIC MENU INFO
|
||||
HEIGHT=8
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ function startOrderBook() {
|
|||
sleep 3
|
||||
dialog \
|
||||
--title "Monitoring the ob-watcher - press CTRL+C to exit" \
|
||||
--prgbox "sudo journalctl -fn20 -u ob-watcher" 30 200
|
||||
--prgbox "sudo journalctl -fn100 -u ob-watcher" -1 -1
|
||||
}
|
||||
|
||||
if [ "$1" = startOrderBookService ]; then
|
||||
|
|
|
|||
|
|
@ -26,17 +26,6 @@ function listCJcandidateTXNs {
|
|||
done
|
||||
}
|
||||
|
||||
function installBoltzmann {
|
||||
if [ ! -f "/home/joinmarket/boltzmann/bvenv/bin/activate" ]; then
|
||||
cd /home/joinmarket/ || exit 1
|
||||
git clone https://code.samourai.io/oxt/boltzmann.git
|
||||
cd boltzmann || exit 1
|
||||
python3 -m venv bvenv
|
||||
source bvenv/bin/activate || exit 1
|
||||
python setup.py install
|
||||
fi
|
||||
}
|
||||
|
||||
function dialog_inputbox {
|
||||
local title=$1
|
||||
local text=$2
|
||||
|
|
@ -66,7 +55,7 @@ isLocalBitcoinCLI=$(sudo -u bitcoin bitcoin-cli -version | grep -c "Bitcoin Core
|
|||
isTxindex=$(sudo -u bitcoin cat /home/bitcoin/.bitcoin/bitcoin.conf | grep -c "txindex=1")
|
||||
|
||||
# BASIC MENU INFO
|
||||
HEIGHT=13
|
||||
HEIGHT=12
|
||||
WIDTH=61
|
||||
CHOICE_HEIGHT=7
|
||||
TITLE="Tools"
|
||||
|
|
@ -97,8 +86,6 @@ if [ "$isLocalBitcoinCLI" -gt 0 ] && [ "$isTxindex" -gt 0 ]; then
|
|||
CHOICE_HEIGHT=$((CHOICE_HEIGHT + 1))
|
||||
fi
|
||||
fi
|
||||
OPTIONS+=(
|
||||
BOLTZMANN "Analyze the entropy of a transaction")
|
||||
if [ "${runningEnv}" != mynode ]; then
|
||||
OPTIONS+=(
|
||||
PASSWORD "Change the ssh password")
|
||||
|
|
@ -186,15 +173,6 @@ CHECKTXN)
|
|||
echo "Press ENTER to return to the menu..."
|
||||
read key
|
||||
;;
|
||||
BOLTZMANN)
|
||||
dialog_inputbox "Boltzmann transaction entropy analysis" "\nUsing: https://code.samourai.io/oxt/boltzmann\n\nPaste a TXID to analyze" 11 71
|
||||
clear
|
||||
installBoltzmann
|
||||
python /home/joinmarket/start.boltzmann.py --txid=$dialog_output
|
||||
echo
|
||||
echo "Press ENTER to return to the menu..."
|
||||
read key
|
||||
;;
|
||||
CJFINDER)
|
||||
BLOCKHEIGHT=$(customRPC "" "getblockchaininfo" "" |
|
||||
grep blocks | awk '{print $2}' | cut -d, -f1)
|
||||
|
|
|
|||
|
|
@ -3,13 +3,16 @@
|
|||
source /home/joinmarket/_functions.sh
|
||||
|
||||
# BASIC MENU INFO
|
||||
HEIGHT=16
|
||||
HEIGHT=18
|
||||
WIDTH=60
|
||||
CHOICE_HEIGHT=7
|
||||
TITLE="Advanced update options"
|
||||
MENU="
|
||||
Current JoininBox version: $currentJBcommit
|
||||
Current JoinMarket version: $currentJMversion"
|
||||
Installed versions:
|
||||
JoininBox $currentJBcommit
|
||||
JoinMarket $currentJMversion
|
||||
$currentBTCversion"
|
||||
|
||||
OPTIONS=()
|
||||
BACKTITLE="JoininBox GUI"
|
||||
|
||||
|
|
|
|||
|
|
@ -3,20 +3,34 @@
|
|||
source /home/joinmarket/_functions.sh
|
||||
|
||||
# BASIC MENU INFO
|
||||
HEIGHT=12
|
||||
WIDTH=56
|
||||
CHOICE_HEIGHT=3
|
||||
HEIGHT=15
|
||||
WIDTH=57
|
||||
CHOICE_HEIGHT=4
|
||||
TITLE="Update options"
|
||||
MENU="
|
||||
Current JoininBox version: $currentJBcommit
|
||||
Current JoinMarket version: $currentJMversion"
|
||||
Installed versions:
|
||||
JoininBox $currentJBcommit
|
||||
JoinMarket $currentJMversion
|
||||
$currentBTCversion"
|
||||
OPTIONS=()
|
||||
BACKTITLE="JoininBox GUI"
|
||||
|
||||
# Basic Options
|
||||
# Determine if using tag or commit for display
|
||||
testedVersion=$(grep 'testedJMversion=' < ~/install.joinmarket.sh | grep -v '^#' | cut -d '"' -f 2)
|
||||
if [ -z "$testedVersion" ]; then
|
||||
testedVersion=$(grep 'testedJMcommit=' < ~/install.joinmarket.sh | cut -d '"' -f 2 | cut -c 1-12)
|
||||
testedVersion="${testedVersion} (commit)"
|
||||
fi
|
||||
OPTIONS+=(
|
||||
JOININBOX "Update the JoininBox scripts and menu"
|
||||
JOINMARKET "Update/reinstall JoinMarket to $(grep testedJMversion= < ~/install.joinmarket.sh | cut -d '"' -f 2)"
|
||||
JOINMARKET "Update/reinstall JoinMarket to ${testedVersion}")
|
||||
|
||||
if [ "$runningEnv" = "standalone" ]; then
|
||||
OPTIONS+=(\
|
||||
BITCOIN "Update Bitcoin Core to a chosen version")
|
||||
fi
|
||||
OPTIONS+=(\
|
||||
ADVANCED "Advanced update options")
|
||||
|
||||
CHOICE=$(dialog --clear \
|
||||
|
|
@ -47,6 +61,14 @@ case $CHOICE in
|
|||
echo
|
||||
echo "Press ENTER to return to the menu"
|
||||
read key;;
|
||||
BITCOIN)
|
||||
/home/joinmarket/standalone/bitcoin.update.sh custom
|
||||
errorOnInstall $?
|
||||
echo
|
||||
echo "# Start bitcoind .. "
|
||||
sudo systemctl start bitcoind
|
||||
echo "# Monitoring the bitcoind logs .. "
|
||||
showBitcoinLogs;;
|
||||
ADVANCED)
|
||||
/home/joinmarket/menu.update.advanced.sh;;
|
||||
esac
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@ Enter the new gap limit to be used" 16 60 2> "$gaplimit"
|
|||
echo
|
||||
/home/joinmarket/start.script.sh wallet-tool "$(cat $wallet)"|grep mixdepth|sed -n '1~2p'|awk '{print $3}'
|
||||
echo
|
||||
echo "Import the master public keys to Specter Desktop or Electrum to create watch only wallets."
|
||||
echo "Import the master public keys to Specter Desktop or Electrum to create watch-only wallets."
|
||||
echo
|
||||
echo "Press ENTER to return to the menu..."
|
||||
read key
|
||||
|
|
|
|||
|
|
@ -73,9 +73,9 @@ case $CHOICE in
|
|||
--msgbox "
|
||||
There are no stats because the Yield Generator was never run.
|
||||
|
||||
Start with the menu option: RUN_YG" 10 50
|
||||
Start with the menu option: MAKER" 10 50
|
||||
else
|
||||
dialog --prgbox "/home/joinmarket/info.stats.sh showAllEarned" 9 55
|
||||
dialog --prgbox "/home/joinmarket/info.stats.sh showAllEarned" 9 67
|
||||
fi;;
|
||||
NICKNAME)
|
||||
name=$(YGnickname)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
if [ ${#1} -eq 0 ]||[ $1 = "-h" ]||[ $1 = "--help" ];then
|
||||
if [ ${#1} -eq 0 ] || [ $1 = "-h" ] || [ $1 = "--help" ]; then
|
||||
echo "Enable or disable ssh access with the joinmarket user"
|
||||
echo "sudo set.ssh.sh [off|on]"
|
||||
echo
|
||||
|
|
@ -18,7 +18,7 @@ if ! grep -Eq "^joinmarketSSH=" /home/joinmarket/joinin.conf; then
|
|||
fi
|
||||
|
||||
echo
|
||||
if [ "$1" = "off" ];then
|
||||
if [ "$1" = "off" ]; then
|
||||
echo "# Disable ssh access with the joinmarket user"
|
||||
if ! grep -Eq "^DenyUsers joinmarket" /etc/ssh/sshd_config; then
|
||||
echo "DenyUsers joinmarket" | tee -a /etc/ssh/sshd_config
|
||||
|
|
@ -35,4 +35,4 @@ elif [ "$1" = "on" ]; then
|
|||
else
|
||||
echo "# Invalid option $*"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ if [ "$1" = "set" ]; then
|
|||
# check that config file exists
|
||||
raspiblitzConfExists=$(ls ${configFile} 2>/dev/null | grep -c "${configFile}")
|
||||
if [ ${raspiblitzConfExists} -eq 0 ]; then
|
||||
echo "# blitz.conf.sh $@"
|
||||
echo "# blitz.conf.sh $*"
|
||||
echo "# FAIL: missing config file: ${configFile}"
|
||||
exit 3
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -49,13 +49,13 @@ function downloadSnapShot() {
|
|||
|
||||
echo "# Check available diskspace"
|
||||
FREE=$(df -k --output=avail "$PWD" | tail -n1) # df -k not df -h
|
||||
if [ $FREE -lt 12582912 ]; then # 12G = 12*1024*1024k
|
||||
if [ $FREE -lt 21000000 ]; then
|
||||
echo "# The free space is only $FREE bytes!"
|
||||
echo "# Would need ~12GB free space to download and extract the snapshot."
|
||||
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 12GB is free!"
|
||||
echo "# OK, more than 21GB is free!"
|
||||
fi
|
||||
sudo -u joinmarket mkdir /home/joinmarket/download 2>/dev/null
|
||||
cd /home/joinmarket/download || exit 1
|
||||
|
|
@ -107,13 +107,13 @@ function downloadSnapShot() {
|
|||
|
||||
echo "# Extracting to /home/store/app-data/.bitcoin ..."
|
||||
FREE=$(df -k --output=avail "$PWD" | tail -n1) # df -k not df -h
|
||||
if [ $FREE -lt 7340032 ]; then # 7G = 7*1024*1024k
|
||||
if [ $FREE -lt 11000000 ]; then
|
||||
echo "# The free space is only $FREE bytes!"
|
||||
echo "# Would need ~7GB free space to extract the snapshot."
|
||||
echo "# Press ENTER to continue to download regardless or CTRL+C to exit."
|
||||
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 7GB is free!"
|
||||
echo "# OK, more than 11GB is free!"
|
||||
fi
|
||||
addUserStore
|
||||
if [ ! -d /home/store/app-data/.bitcoin ]; then
|
||||
|
|
@ -140,7 +140,11 @@ function downloadSnapShot() {
|
|||
|
||||
echo "# Unzip ..."
|
||||
sudo apt-get install -y unzip
|
||||
sudo -u bitcoin unzip -o $downloadFileName -d /home/store/app-data/.bitcoin
|
||||
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 \
|
||||
|
|
@ -151,8 +155,8 @@ function downloadSnapShot() {
|
|||
function installBitcoinCoreStandalone() {
|
||||
downloadBitcoinCore
|
||||
|
||||
if [ -f /home/bitcoin/bitcoin/bitcoind ]; then
|
||||
installedVersion=$(/home/bitcoin/bitcoin/bitcoind --version | grep version)
|
||||
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"
|
||||
|
|
@ -162,15 +166,10 @@ function installBitcoinCoreStandalone() {
|
|||
echo "# Add the joinmarket user to the bitcoin group"
|
||||
sudo usermod -aG bitcoin joinmarket
|
||||
echo "# Installing Bitcoin Core v${bitcoinVersion}"
|
||||
sudo -u bitcoin mkdir -p /home/bitcoin/bitcoin
|
||||
cd /home/joinmarket/download/bitcoin-${bitcoinVersion}/bin/ || exit 1
|
||||
sudo install -m 0755 -o root -g root -t /home/bitcoin/bitcoin ./*
|
||||
sudo install -m 0755 -o root -g root -t /usr/local/bin/ ./*
|
||||
fi
|
||||
if [ "$(grep -c "/home/bitcoin/bitcoin" </etc/profile)" -eq 0 ]; then
|
||||
echo "# Add /home/bitcoin/bitcoin to global PATH"
|
||||
echo "PATH=/home/bitcoin/bitcoin:$PATH" | sudo tee -a /etc/profile
|
||||
fi
|
||||
if ! sudo -u bitcoin /home/bitcoin/bitcoin/bitcoind --version | grep "Bitcoin Core version"; then
|
||||
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
|
||||
|
|
@ -220,24 +219,45 @@ function installMainnet() {
|
|||
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
|
||||
Type=forking
|
||||
PIDFile=/home/bitcoin/bitcoin/bitcoind.pid
|
||||
ExecStart=/home/bitcoin/bitcoin/bitcoind -daemon \
|
||||
-pid=/home/bitcoin/bitcoin/bitcoind.pid
|
||||
Restart=always
|
||||
TimeoutSec=120
|
||||
RestartSec=30
|
||||
|
||||
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
|
||||
|
|
@ -247,9 +267,17 @@ WantedBy=multi-user.target
|
|||
echo "# OK - the bitcoind.service is now enabled"
|
||||
|
||||
# add aliases
|
||||
if [ $(alias | grep -c "sudo -u bitcoin /home/bitcoin/bitcoin/bitcoin-cli") -eq 0 ]; then
|
||||
sudo bash -c "echo 'alias bitcoin-cli=\"sudo -u bitcoin /home/bitcoin/bitcoin/bitcoin-cli\"' >> /home/joinmarket/_aliases.sh"
|
||||
sudo bash -c "echo 'alias bitcoind=\"sudo -u bitcoin /home/bitcoin/bitcoin/bitcoind\"' >> /home/joinmarket/_aliases.sh"
|
||||
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
|
||||
|
|
@ -257,14 +285,14 @@ WantedBy=multi-user.target
|
|||
|
||||
sudo systemctl start bitcoind
|
||||
echo
|
||||
echo "# Installed $(sudo -u bitcoin /home/bitcoin/bitcoin/bitcoind --version | grep version)"
|
||||
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 [ ! -f /home/bitcoin/.bitcoin/mainnet/wallets/wallet.dat/wallet.dat ]; then
|
||||
echo "# Create wallet.dat ..."
|
||||
if [ ! -d /home/bitcoin/.bitcoin/wallets/watch-only-descriptor-wallet ]; then
|
||||
echo "# Create watch-only-descriptor-wallet ..."
|
||||
sleep 10
|
||||
sudo -u bitcoin /home/bitcoin/bitcoin/bitcoin-cli -named createwallet wallet_name=wallet.dat descriptors=false
|
||||
sudo -u bitcoin /usr/local/bin/bitcoin-cli -named createwallet wallet_name=watch-only-descriptor-wallet descriptors=true disable_private_keys=true
|
||||
fi
|
||||
}
|
||||
|
|
|
|||
219
scripts/standalone/bitcoin.update.sh
Normal file
219
scripts/standalone/bitcoin.update.sh
Normal file
|
|
@ -0,0 +1,219 @@
|
|||
#!/bin/bash
|
||||
|
||||
# command info
|
||||
if [ $# -eq 0 ] || [ "$1" = "-h" ] || [ "$1" = "-help" ]; then
|
||||
echo "Interim optional Bitcoin Core updates."
|
||||
echo "bitcoin.update.sh [info|tested|reckless|custom]"
|
||||
echo "info -> get actual state and possible actions"
|
||||
echo "tested -> only do a tested update by the RaspiBlitz team"
|
||||
echo "reckless -> the update was not tested by the RaspiBlitz team"
|
||||
echo "custom <version> <skipverify> -> update to a chosen version"
|
||||
echo " the binary checksum and signatures will be checked in all cases"
|
||||
echo " except when 'skipverify' is used"
|
||||
echo
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "# Running: bitcoin.update.sh $*"
|
||||
|
||||
# 1. parameter [info|tested|reckless]
|
||||
mode="$1"
|
||||
|
||||
# RECOMMENDED UPDATE BY RASPIBLITZ TEAM (just possible once per sd card update)
|
||||
# comment will be shown as "BEWARE Info" when option is chosen (can be multiple lines)
|
||||
bitcoinVersion="" # example: 22.0 .. keep empty if no newer version as sd card build is available
|
||||
|
||||
# GATHER DATA
|
||||
# setting download directory to the current user
|
||||
downloadDir="/home/$(whoami)/download/bitcoin.update"
|
||||
|
||||
# bitcoinOSversion
|
||||
if [ "$(uname -m | grep -c 'arm')" -gt 0 ]; then
|
||||
bitcoinOSversion="arm-linux-gnueabihf"
|
||||
elif [ "$(uname -m | grep -c 'aarch64')" -gt 0 ]; then
|
||||
bitcoinOSversion="aarch64-linux-gnu"
|
||||
elif [ "$(uname -m | grep -c 'x86_64')" -gt 0 ]; then
|
||||
bitcoinOSversion="x86_64-linux-gnu"
|
||||
fi
|
||||
|
||||
# installed version
|
||||
installedVersion=$(sudo -u bitcoin /usr/local/bin/bitcoind --version | head -n1 | cut -d" " -f4 | cut -c 2-)
|
||||
|
||||
# test if the installed version already the tested/recommended update version
|
||||
bitcoinUpdateInstalled=$(echo "${installedVersion}" | grep -c "${bitcoinVersion}")
|
||||
|
||||
# get latest release from GitHub releases
|
||||
bitcoinLatestVersion=$(curl --header "X-GitHub-Api-Version:2022-11-28" -s https://api.github.com/repos/bitcoin/bitcoin/releases | jq -r '.[].tag_name' | sort | tail -n1 | cut -c 2-)
|
||||
|
||||
# INFO
|
||||
function displayInfo() {
|
||||
echo "# basic data"
|
||||
echo "installedVersion='${installedVersion}'"
|
||||
echo "bitcoinOSversion='${bitcoinOSversion}'"
|
||||
|
||||
echo "# the tested/recommended update option"
|
||||
echo "bitcoinUpdateInstalled='${bitcoinUpdateInstalled}'"
|
||||
echo "bitcoinVersion='${bitcoinVersion}'"
|
||||
|
||||
echo "# reckless update option (latest Bitcoin Core release from GitHub)"
|
||||
echo "bitcoinLatestVersion='${bitcoinLatestVersion}'"
|
||||
}
|
||||
|
||||
if [ "${mode}" = "info" ]; then
|
||||
displayInfo
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# tested
|
||||
if [ "${mode}" = "tested" ]; then
|
||||
|
||||
echo "# bitcoin.update.sh tested"
|
||||
|
||||
elif [ "${mode}" = "reckless" ]; then
|
||||
# RECKLESS
|
||||
# this mode is just for people running test and development nodes - its not recommended
|
||||
# for production nodes. In a update/recovery scenario it will not install a fixed version
|
||||
# it will always pick the latest release from the github
|
||||
echo "# bitcoin.update.sh reckless"
|
||||
bitcoinVersion=${bitcoinLatestVersion}
|
||||
pathVersion=${bitcoinVersion}
|
||||
|
||||
elif [ "${mode}" = "custom" ]; then
|
||||
if [ $# -gt 1 ]; then
|
||||
bitcoinVersion="$2"
|
||||
else
|
||||
clear
|
||||
echo
|
||||
echo "# Update Bitcoin Core to a chosen version."
|
||||
echo
|
||||
echo "# Input the version you would like to install and press ENTER."
|
||||
echo "# Examples (versions below 22.1 are not supported):"
|
||||
echo "24.0.1"
|
||||
echo "26.0"
|
||||
echo
|
||||
read bitcoinVersion
|
||||
fi
|
||||
|
||||
if [ $(echo ${bitcoinVersion} | grep -c "rc") -gt 0 ]; then
|
||||
cutVersion=$(echo ${bitcoinVersion} | awk -F"r" '{print $1}')
|
||||
rcVersion=$(echo ${bitcoinVersion} | awk -F"r" '{print $2}')
|
||||
# https://bitcoincore.org/bin/bitcoin-core-22.0/test.rc3/
|
||||
pathVersion=${cutVersion}/test.r${rcVersion}
|
||||
else
|
||||
pathVersion=${bitcoinVersion}
|
||||
fi
|
||||
|
||||
if curl --output /dev/null --silent --head --fail \
|
||||
https://bitcoincore.org/bin/bitcoin-core-${pathVersion}/SHA256SUMS.asc; then
|
||||
echo "# OK version exists at https://bitcoincore.org/bin/bitcoin-core-${pathVersion}"
|
||||
if [ "${mode}" = "custom" ] && [ "$3" = "skipverify" ]; then
|
||||
echo "# skipping signature verification"
|
||||
fi
|
||||
echo "# Press ENTER to proceed to install Bitcoin Core $bitcoinVersion or CTRL+C to abort."
|
||||
read key
|
||||
else
|
||||
echo "# FAIL $bitcoinVersion does not exist"
|
||||
echo
|
||||
echo "# Press ENTER to return to the main menu"
|
||||
read key
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# JOINED INSTALL
|
||||
if [ "${mode}" = "tested" ] || [ "${mode}" = "reckless" ] || [ "${mode}" = "custom" ]; then
|
||||
|
||||
displayInfo
|
||||
|
||||
if [ "$installedVersion" = "$bitcoinVersion" ]; then
|
||||
echo "# installedVersion = bitcoinVersion"
|
||||
echo "# exiting script"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "# clean & change into download directory"
|
||||
sudo rm -rf "${downloadDir}"
|
||||
mkdir -p "${downloadDir}"
|
||||
cd "${downloadDir}" || exit 1
|
||||
|
||||
echo "# Receive signer keys"
|
||||
curl -s "https://api.github.com/repos/bitcoin-core/guix.sigs/contents/builder-keys" |
|
||||
jq -r '.[].download_url' | while read url; do curl -s "$url" | gpg --import; done
|
||||
|
||||
# download signed binary sha256 hash sum file
|
||||
wget --prefer-family=ipv4 --progress=bar:force -O SHA256SUMS https://bitcoincore.org/bin/bitcoin-core-${bitcoinVersion}/SHA256SUMS
|
||||
# download the signed binary sha256 hash sum file and check
|
||||
wget --prefer-family=ipv4 --progress=bar:force -O SHA256SUMS.asc https://bitcoincore.org/bin/bitcoin-core-${bitcoinVersion}/SHA256SUMS.asc
|
||||
|
||||
if [ "${mode}" = "custom" ] && [ "$3" = "skipverify" ]; then
|
||||
echo "# skipping signature verification"
|
||||
echo "# display the output of 'gpg --verify SHA256SUMS.asc'"
|
||||
gpg --verify SHA256SUMS.asc
|
||||
else
|
||||
if gpg --verify SHA256SUMS.asc; then
|
||||
echo
|
||||
echo "****************************************"
|
||||
echo "OK --> BITCOIN MANIFEST IS CORRECT"
|
||||
echo "****************************************"
|
||||
echo
|
||||
else
|
||||
echo
|
||||
echo "# BUILD FAILED --> the PGP verification failed"
|
||||
echo "# try again or with a different version"
|
||||
echo "# if you want to skip verifying all signatures (and just show them) use the command:"
|
||||
echo "# /home/admin/config.scripts/bonus.bitcoin.sh custom ${bitcoinVersion:-<version>} skipverify"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "# Downloading Bitcoin Core v${bitcoinVersion} for ${bitcoinOSversion} ..."
|
||||
binaryName="bitcoin-${bitcoinVersion}-${bitcoinOSversion}.tar.gz"
|
||||
wget https://bitcoincore.org/bin/bitcoin-core-${pathVersion}/${binaryName}
|
||||
if [ ! -f "./${binaryName}" ]; then
|
||||
echo "# FAIL # Downloading BITCOIN BINARY did not succeed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "# Checking the binary checksum ..."
|
||||
if ! sha256sum -c --ignore-missing SHA256SUMS; then
|
||||
# get the sha256 value for the corresponding platform from signed hash sum file
|
||||
bitcoinSHA256=$(grep -i "${binaryName}}" SHA256SUMS | cut -d " " -f1)
|
||||
echo "# FAIL # Downloaded BITCOIN BINARY CHECKSUM:"
|
||||
echo "$(sha256sum ${binaryName})"
|
||||
echo "NOT matching SHA256 checksum:"
|
||||
echo "${bitcoinSHA256}"
|
||||
exit 1
|
||||
else
|
||||
echo
|
||||
echo "# OK --> VERIFIED BITCOIN CORE BINARY CHECKSUM IS CORRECT"
|
||||
echo
|
||||
fi
|
||||
fi
|
||||
|
||||
# JOINED INSTALL
|
||||
if [ "${mode}" = "tested" ] || [ "${mode}" = "reckless" ] || [ "${mode}" = "custom" ]; then
|
||||
|
||||
# install
|
||||
echo "# Stopping bitcoind ..."
|
||||
sudo systemctl stop bitcoind 2>/dev/null
|
||||
sudo systemctl stop tbitcoind 2>/dev/null
|
||||
sudo systemctl stop sbitcoind 2>/dev/null
|
||||
echo
|
||||
echo "# Installing Bitcoin Core v${bitcoinVersion}"
|
||||
tar -xvf ${binaryName}
|
||||
sudo install -m 0755 -o root -g root -t /usr/local/bin/ bitcoin-${bitcoinVersion}/bin/*
|
||||
sleep 3
|
||||
if ! sudo /usr/local/bin/bitcoind --version | grep "${bitcoinVersion}"; then
|
||||
echo
|
||||
echo "# BUILD FAILED --> Was not able to install bitcoind version(${bitcoinVersion})"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "# OK Bitcoin Core ${bitcoinVersion} is installed"
|
||||
exit 0
|
||||
|
||||
else
|
||||
echo "# error='parameter not known'"
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -21,3 +21,7 @@ echo "***********************************************" >> $logFile
|
|||
|
||||
# make sure SSH server is configured & running
|
||||
sudo /home/joinmarket/standalone/ssh.sh checkrepair >> ${logFile}
|
||||
|
||||
# fix ownership of possibly migrated files
|
||||
sudo chown -R bitcoin:bitcoin /home/bitcoin/
|
||||
sudo chown -R joinmarket:joinmarket /home/joinmarket/
|
||||
|
|
|
|||
296
scripts/standalone/install.i2pd.sh
Normal file
296
scripts/standalone/install.i2pd.sh
Normal file
|
|
@ -0,0 +1,296 @@
|
|||
#!/bin/bash
|
||||
|
||||
# https://i2pd.readthedocs.io
|
||||
|
||||
if [ $# -eq 0 ] || [ "$1" = "-h" ] || [ "$1" = "-help" ]; then
|
||||
echo "I2P Daemon install script"
|
||||
echo "More info at https://i2pd.readthedocs.io"
|
||||
echo "Usage:"
|
||||
echo "install.i2pd.sh install -> Install i2pd"
|
||||
echo "install.i2pd.sh on -> Switch on i2pd"
|
||||
echo "install.i2pd.sh off -> Uninstall i2pd"
|
||||
echo "install.i2pd.sh addseednodes -> Add 21 randonly selected I2P seed nodes from: https://github.com/bitcoin/bitcoin/blob/master/contrib/seeds/nodes_main.txt"
|
||||
echo "install.i2pd.sh status -> I2P related logs from bitcoind, bitcoin-cli -netinfo 4 and webconsole access"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
function confAdd {
|
||||
# get parameters
|
||||
keystr="$1"
|
||||
valuestr=$(echo "$2" | sed 's/\//\\\//g')
|
||||
configFile="$3"
|
||||
|
||||
# check if key needs to be added (prepare new entry)
|
||||
entryExists=$(grep -c "^${keystr}=" ${configFile})
|
||||
if [ ${entryExists} -eq 0 ]; then
|
||||
echo "${keystr}=" | sudo tee -a ${configFile} 1>/dev/null
|
||||
fi
|
||||
|
||||
# add an extra key=value line (needs sudo to operate when user is not root)
|
||||
echo "${keystr}=${valuestr}" | sudo tee -a ${configFile}
|
||||
}
|
||||
|
||||
function add_repo {
|
||||
# Add repo for the latest version
|
||||
# i2pd — https://repo.i2pd.xyz/.help/readme.txt
|
||||
# https://repo.i2pd.xyz/.help/add_repo
|
||||
|
||||
source /etc/os-release
|
||||
DIST=$ID
|
||||
case $ID in
|
||||
debian | ubuntu | raspbian)
|
||||
if [[ -n $DEBIAN_CODENAME ]]; then
|
||||
VERSION_CODENAME=$DEBIAN_CODENAME
|
||||
fi
|
||||
if [[ -n $UBUNTU_CODENAME ]]; then
|
||||
VERSION_CODENAME=$UBUNTU_CODENAME
|
||||
fi
|
||||
if [[ -z $VERSION_CODENAME ]]; then
|
||||
echo "Couldn't find VERSION_CODENAME in your /etc/os-release file. Did your system supported? Please report issue to me by writing to email: 'r4sas <at> i2pd.xyz'"
|
||||
exit 1
|
||||
fi
|
||||
RELEASE=$VERSION_CODENAME
|
||||
;;
|
||||
*)
|
||||
if [[ -z $ID_LIKE || "$ID_LIKE" != "debian" && "$ID_LIKE" != "ubuntu" ]]; then
|
||||
echo "Your system is not supported by this script. Currently it supports debian-like and ubuntu-like systems."
|
||||
exit 1
|
||||
else
|
||||
DIST=$ID_LIKE
|
||||
case $ID_LIKE in
|
||||
debian)
|
||||
if [[ "$ID" == "kali" ]]; then
|
||||
if [[ "$VERSION" == "2019"* || "$VERSION" == "2020"* ]]; then
|
||||
RELEASE="buster"
|
||||
elif [[ "$VERSION" == "2021"* || "$VERSION" == "2022"* ]]; then
|
||||
RELEASE="bullseye"
|
||||
fi
|
||||
else
|
||||
RELEASE=$DEBIAN_CODENAME
|
||||
fi
|
||||
;;
|
||||
ubuntu)
|
||||
RELEASE=$UBUNTU_CODENAME
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
if [[ -z $RELEASE ]]; then
|
||||
echo "Couldn't detect your system release. Please report issue to me by writing to email: 'r4sas <at> i2pd.xyz'"
|
||||
exit 1
|
||||
fi
|
||||
echo "Importing signing key"
|
||||
wget -q -O - https://repo.i2pd.xyz/r4sas.gpg | sudo apt-key --keyring /etc/apt/trusted.gpg.d/i2pd.gpg add -
|
||||
echo "Adding APT repository"
|
||||
echo "deb https://repo.i2pd.xyz/$DIST $RELEASE main" | sudo tee /etc/apt/sources.list.d/i2pd.list
|
||||
echo "deb-src https://repo.i2pd.xyz/$DIST $RELEASE main" | sudo tee -a /etc/apt/sources.list.d/i2pd.list
|
||||
}
|
||||
|
||||
function bitcoinI2Pstatus {
|
||||
echo "# I2P related logs from the bitcoin debug log"
|
||||
echo "sudo tail -n 200 ${bitcoinLogPath} | grep i2p"
|
||||
echo
|
||||
sudo cat ${bitcoinLogPath} | grep i2p
|
||||
echo
|
||||
echo "# Running the command:"
|
||||
echo "sudo -u bitcoin /home/bitcoin/bitcoin/bitcoin-cli -netinfo 4"
|
||||
echo
|
||||
sudo -u bitcoin /home/bitcoin/bitcoin/bitcoin-cli -netinfo 4
|
||||
echo
|
||||
echo "# i2pd webconsole:"
|
||||
localip=$(hostname -I | awk '{print $1}')
|
||||
echo "http://${localip}:7070"
|
||||
echo "# Username: i2pd"
|
||||
echo "# Password: your passwordB"
|
||||
echo
|
||||
}
|
||||
|
||||
echo "# Running: 'install.i2pd.sh $*'"
|
||||
source /home/joinmarket/joinin.conf
|
||||
|
||||
bitcoinConfPath="/home/bitcoin/.bitcoin/bitcoin.conf"
|
||||
bitcoinLogPath="/home/bitcoin/.bitcoin/debug.log"
|
||||
|
||||
# make sure to be present in PATH
|
||||
if ! echo "$PATH" | grep "/usr/sbin" >/dev/null; then
|
||||
export PATH=$PATH:/usr/sbin
|
||||
echo "PATH=\$PATH:/usr/sbin" | sudo tee -a /etc/profile
|
||||
fi
|
||||
|
||||
if [ "$1" = "install" ]; then
|
||||
|
||||
isInstalled=$(sudo systemctl list-unit-files | grep -c i2pd)
|
||||
if [ "${isInstalled}" != "0" ]; then
|
||||
echo "# i2pd is already installed."
|
||||
else
|
||||
echo "# Installing i2pd ..."
|
||||
|
||||
add_repo
|
||||
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y i2pd
|
||||
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$1" = "1" ] || [ "$1" = "on" ]; then
|
||||
|
||||
isInstalled=$(sudo systemctl list-unit-files | grep -c i2pd)
|
||||
if [ "${isInstalled}" != "0" ]; then
|
||||
echo "# i2pd is installed."
|
||||
else
|
||||
/home/joinmarket/standalone/install.i2pd.sh install
|
||||
fi
|
||||
|
||||
if systemctl is-active --quiet i2pd.service; then
|
||||
echo "# i2pd.service is already active."
|
||||
else
|
||||
echo "# sudo systemctl enable i2pd"
|
||||
sudo systemctl enable i2pd
|
||||
fi
|
||||
|
||||
echo "# i2pd config"
|
||||
/home/joinmarket/set.value.sh set debug tor ${bitcoinConfPath} noquotes
|
||||
confAdd debug i2p ${bitcoinConfPath}
|
||||
/home/joinmarket/set.value.sh set i2psam 127.0.0.1:7656 ${bitcoinConfPath} noquotes
|
||||
/home/joinmarket/set.value.sh set i2pacceptincoming 1 ${bitcoinConfPath} noquotes
|
||||
/home/joinmarket/set.value.sh set onlynet onion ${bitcoinConfPath} noquotes
|
||||
confAdd onlynet i2p ${bitcoinConfPath}
|
||||
PASSWORD_B=$(sudo cat ${bitcoinConfPath} | grep rpcpassword | cut -c 13-)
|
||||
cat <<EOF | sudo tee /etc/i2pd/i2pd.conf
|
||||
# i2pd settings for the Joininbox
|
||||
# for the defaults see:
|
||||
# https://github.com/PurpleI2P/i2pd/blob/openssl/contrib/i2pd.conf
|
||||
# Docs:
|
||||
# https://i2pd.readthedocs.io/en/latest/user-guide/configuration/
|
||||
loglevel = none
|
||||
[http]
|
||||
address=0.0.0.0
|
||||
strictheaders = false
|
||||
port = 7070
|
||||
auth = true
|
||||
user = i2pd
|
||||
pass = ${PASSWORD_B}
|
||||
[httpproxy]
|
||||
enabled = false
|
||||
[socksproxy]
|
||||
enabled = false
|
||||
[sam]
|
||||
enabled = true
|
||||
[bob]
|
||||
enabled = false
|
||||
[i2cp]
|
||||
enabled = false
|
||||
[i2pcontrol]
|
||||
enabled = false
|
||||
[upnp]
|
||||
enabled = false
|
||||
EOF
|
||||
|
||||
sudo ufw allow 7070 comment "i2pd-webconsole"
|
||||
|
||||
echo "# Start i2pd ..."
|
||||
sudo systemctl start i2pd
|
||||
echo "# Restart bitcoind ..."
|
||||
sudo systemctl restart bitcoind 2>/dev/null
|
||||
sleep 10
|
||||
|
||||
if i2pd --version; then
|
||||
echo "# Installed i2pd"
|
||||
else
|
||||
echo "# i2pd is not installed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# setting value in raspiblitz.conf
|
||||
/home/joinmarket/set.value.sh set i2pd "on"
|
||||
|
||||
localip=$(hostname -I | awk '{print $1}')
|
||||
echo "# Config: /etc/i2pd/i2pd.conf"
|
||||
echo "# i2pd web console: ${localip}:7070"
|
||||
echo "# Monitor i2p in bitcoind:"
|
||||
echo "sudo tail -n 100 ${bitcoinLogPath} | grep i2p"
|
||||
echo "sudo -u bitcoin /home/bitcoin/bitcoin/bitcoin-cli -netinfo 4"
|
||||
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$1" = "addseednodes" ]; then
|
||||
|
||||
if ! sudo -u bitcoin /home/bitcoin/bitcoin/bitcoin-cli -netinfo 4 | grep i2p; then
|
||||
echo "# i2pd is not running"
|
||||
/home/joinmarket/standalone/install.i2pd.sh on
|
||||
fi
|
||||
|
||||
echo "Add 21 randomly selected I2P seed nodes from: https://github.com/bitcoin/bitcoin/blob/master/contrib/seeds/nodes_main.txt"
|
||||
echo "Monitor in a new terminal with:"
|
||||
echo "watch sudo -u bitcoin /home/bitcoin/bitcoin/bitcoin-cli -netinfo 4"
|
||||
echo "This will take some time ..."
|
||||
|
||||
# Fetch and filter the list of seed nodes
|
||||
i2pSeedNodeList=$(curl -sS https://raw.githubusercontent.com/bitcoin/bitcoin/master/contrib/seeds/nodes_main.txt | grep .b32.i2p:0)
|
||||
|
||||
# Shuffle the list and pick the first 21 nodes
|
||||
selectedNodes=$(echo "$i2pSeedNodeList" | shuf | head -n 21)
|
||||
|
||||
# Add each selected node
|
||||
for i2pSeedNode in ${selectedNodes}; do
|
||||
echo "# Add i2p seed node: ${i2pSeedNode} by running:"
|
||||
echo "bitcoin-cli addnode $i2pSeedNode onetry"
|
||||
sudo -u bitcoin /home/bitcoin/bitcoin/bitcoin-cli addnode "$i2pSeedNode" "onetry"
|
||||
done
|
||||
|
||||
echo
|
||||
echo "# Display sudo tail -n 100 ${bitcoinLogPath} | grep i2p"
|
||||
sudo tail -n 100 ${bitcoinLogPath} | grep i2p
|
||||
echo
|
||||
echo "# Display bitcoin-cli -netinfo 4"
|
||||
sudo -u bitcoin /home/bitcoin/bitcoin/bitcoin-cli -netinfo 4
|
||||
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# switch off
|
||||
if [ "$1" = "0" ] || [ "$1" = "off" ]; then
|
||||
|
||||
echo "# stop & remove systemd service"
|
||||
sudo systemctl stop i2pd 2>/dev/null
|
||||
sudo systemctl disable i2pd.service
|
||||
|
||||
echo "# Uninstall with apt"
|
||||
sudo apt remove -y i2pd
|
||||
|
||||
echo "# Remove settings from bitcoind"
|
||||
/home/joinmarket/set.value.sh delete debug ${bitcoinConfPath} noquotes
|
||||
/home/joinmarket/set.value.sh set debug tor ${bitcoinConfPath} noquotes
|
||||
/home/joinmarket/set.value.sh delete i2psam ${bitcoinConfPath} noquotes
|
||||
/home/joinmarket/set.value.sh delete i2pacceptincoming ${bitcoinConfPath} noquotes
|
||||
/home/joinmarket/set.value.sh delete onlynet ${bitcoinConfPath} noquotes
|
||||
/home/joinmarket/set.value.sh set onlynet onion ${bitcoinConfPath} noquotes
|
||||
|
||||
sudo rm /etc/systemd/system/i2pd.service
|
||||
|
||||
sudo ufw delete allow 7070
|
||||
|
||||
if ! i2pd --version 2>/dev/null; then
|
||||
echo "# OK - i2pd is not installed now"
|
||||
else
|
||||
echo "# i2pd is still installed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# setting value in raspiblitz.conf
|
||||
/home/joinmarket/set.value.sh set i2pd "off"
|
||||
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$1" = "status" ]; then
|
||||
bitcoinI2Pstatus
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "# FAIL - Unknown Parameter $1"
|
||||
exit 1
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
source /home/joinmarket/_functions.sh
|
||||
|
||||
# add default value to config if needed
|
||||
|
|
|
|||
|
|
@ -1,62 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import configparser
|
||||
import os
|
||||
import sys
|
||||
import getopt
|
||||
|
||||
def main(argv):
|
||||
|
||||
description = "\nBoltzmann - https://code.samourai.io/oxt/boltzmann/\n\
|
||||
A python script computing the entropy of Bitcoin transactions and the linkability of their inputs and outputs.\n\
|
||||
For a description of the metrics and related discussions:\n\
|
||||
Bitcoin Transactions & Privacy (part 1) : https://gist.github.com/LaurentMT/e758767ca4038ac40aaf\n\
|
||||
Bitcoin Transactions & Privacy (part 2) : https://gist.github.com/LaurentMT/d361bca6dc52868573a2\n\
|
||||
Bitcoin Transactions & Privacy (part 3) : https://gist.github.com/LaurentMT/e8644d5bc903f02613c6\n\
|
||||
\n\
|
||||
WARNING: this feature is highly experimental and not optimised to be used with JoinMarket."
|
||||
os.system('clear')
|
||||
print(description)
|
||||
|
||||
txids = ''
|
||||
try:
|
||||
opts, args = getopt.getopt(argv,"t:",["txids="])
|
||||
except getopt.GetoptError:
|
||||
print('python run.boltzmann.py --txids=TXID1,TXID2')
|
||||
sys.exit(2)
|
||||
|
||||
for opt, arg in opts:
|
||||
if opt in ('-t', '--txids'):
|
||||
txids = arg
|
||||
config = configparser.ConfigParser(strict=False)
|
||||
|
||||
config.read('/home/joinmarket/.joinmarket/joinmarket.cfg')
|
||||
|
||||
rpc_user = config['BLOCKCHAIN']['rpc_user']
|
||||
rpc_password = config['BLOCKCHAIN']['rpc_password']
|
||||
rpc_host = config['BLOCKCHAIN']['rpc_host']
|
||||
rpc_port = config['BLOCKCHAIN']['rpc_port']
|
||||
|
||||
tor = ''
|
||||
if rpc_host.find('.onion') >= 0:
|
||||
print('# Connecting to bitcoind RPC over Tor')
|
||||
tor = 'torsocks'
|
||||
|
||||
boltzmannpath = "/home/joinmarket/boltzmann/"
|
||||
|
||||
bvenv = ". "+boltzmannpath+"bvenv/bin/activate"
|
||||
|
||||
boltzmann = tor+" python "+boltzmannpath+"boltzmann/ludwig.py -p -x 30 \
|
||||
--txids="+txids
|
||||
|
||||
run = bvenv+";"+"export BOLTZMANN_RPC_USERNAME="+rpc_user+";\
|
||||
export BOLTZMANN_RPC_PASSWORD="+rpc_password+";\
|
||||
export BOLTZMANN_RPC_HOST="+rpc_host+";\
|
||||
export BOLTZMANN_RPC_PORT="+rpc_port+";"+boltzmann+" 2>/dev/null"
|
||||
|
||||
print('# Exporting RPC connection details')
|
||||
print('# Running the command:\n'+boltzmann+'\n')
|
||||
os.system(run)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main(sys.argv[1:])
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
echo "# starting JoininBox ..."
|
||||
|
||||
if [ ! -f /home/joinmarket/joinin.conf ];then
|
||||
if [ ! -f /home/joinmarket/joinin.conf ]; then
|
||||
touch /home/joinmarket/joinin.conf
|
||||
fi
|
||||
|
||||
|
|
@ -12,45 +12,44 @@ source /home/joinmarket/_functions.sh
|
|||
# FIRST RUN #
|
||||
#############
|
||||
|
||||
setupStepEntry=$(grep -c "setupStep" < $joininConfPath)
|
||||
if [ "$setupStepEntry" -eq 0 ];then
|
||||
echo "setupStep=0" >> $joininConfPath
|
||||
setupStepEntry=$(grep -c "setupStep" <$joininConfPath)
|
||||
if [ "$setupStepEntry" -eq 0 ]; then
|
||||
echo "setupStep=0" >>$joininConfPath
|
||||
fi
|
||||
|
||||
source /home/joinmarket/joinin.conf
|
||||
if [ "$setupStep" -lt 100 ];then
|
||||
if [ "$setupStep" -lt 5 ];then
|
||||
if [ "$setupStep" -lt 100 ]; then
|
||||
if [ "$setupStep" -lt 5 ]; then
|
||||
# identify running env
|
||||
runningEnvEntry=$(grep -c "runningEnv" < $joininConfPath)
|
||||
if [ "$runningEnvEntry" -eq 0 ];then
|
||||
if [ -f "/mnt/hdd/raspiblitz.conf" ];then
|
||||
runningEnvEntry=$(grep -c "runningEnv" <$joininConfPath)
|
||||
if [ "$runningEnvEntry" -eq 0 ]; then
|
||||
if [ -f "/mnt/hdd/raspiblitz.conf" ] || [ -f "/mnt/hdd/app-data/raspiblitz.conf" ] ; then
|
||||
runningEnv="raspiblitz"
|
||||
elif [ -f "/usr/share/mynode/mynode_config.sh" ];then
|
||||
elif [ -f "/usr/share/mynode/mynode_config.sh" ]; then
|
||||
runningEnv="mynode"
|
||||
else
|
||||
runningEnv="standalone"
|
||||
fi
|
||||
echo "runningEnv=$runningEnv" >> $joininConfPath
|
||||
sed -i "s#setupStep=.*#setupStep=1#g" $joininConfPath
|
||||
echo "runningEnv=$runningEnv" >>$joininConfPath
|
||||
sed -i "s#setupStep=.*#setupStep=1#g" $joininConfPath
|
||||
fi
|
||||
echo "# running in the environment: $runningEnv"
|
||||
|
||||
# identify cpu architecture
|
||||
cpuEntry=$(grep -c "cpu" < $joininConfPath)
|
||||
if [ "$cpuEntry" -eq 0 ];then
|
||||
cpuEntry=$(grep -c "cpu" <$joininConfPath)
|
||||
if [ "$cpuEntry" -eq 0 ]; then
|
||||
cpu=$(uname -m)
|
||||
echo "cpu=$cpu" >> $joininConfPath
|
||||
sed -i "s#setupStep=.*#setupStep=2#g" $joininConfPath
|
||||
echo "cpu=$cpu" >>$joininConfPath
|
||||
sed -i "s#setupStep=.*#setupStep=2#g" $joininConfPath
|
||||
fi
|
||||
echo "# cpu=${cpu}"
|
||||
|
||||
# check Tor
|
||||
torEntry=$(grep -c "runBehindTor" < $joininConfPath)
|
||||
if [ "$torEntry" -eq 0 ];then
|
||||
torEntry=$(grep -c "runBehindTor" <$joininConfPath)
|
||||
if [ "$torEntry" -eq 0 ]; then
|
||||
torTest=$(curl --socks5 localhost:9050 --socks5-hostname localhost:9050 -s \
|
||||
https://check.torproject.org/ | cat | grep -m 1 Congratulations | xargs)
|
||||
if [ "$torTest" = "Congratulations. This browser is configured to use Tor." ]
|
||||
then
|
||||
https://check.torproject.org/ | cat | grep -m 1 Congratulations | xargs)
|
||||
if [ "$torTest" = "Congratulations. This browser is configured to use Tor." ]; then
|
||||
runBehindTor=on
|
||||
else
|
||||
runBehindTor=off
|
||||
|
|
@ -59,65 +58,65 @@ if [ "$setupStep" -lt 100 ];then
|
|||
echo "# Press ENTER to continue without Tor or CTRL+C to cancel and try checking again with 'menu'"
|
||||
read key
|
||||
fi
|
||||
echo "runBehindTor=$runBehindTor" >> $joininConfPath
|
||||
echo "runBehindTor=$runBehindTor" >>$joininConfPath
|
||||
echo "# runBehindTor=$runBehindTor"
|
||||
fi
|
||||
|
||||
# make sure Tor path is known
|
||||
DirEntry=$(grep -c "HiddenServiceDir" < $joininConfPath)
|
||||
if [ "$DirEntry" -eq 0 ];then
|
||||
if [ -d "/mnt/hdd/tor" ];then
|
||||
DirEntry=$(grep -c "HiddenServiceDir" <$joininConfPath)
|
||||
if [ "$DirEntry" -eq 0 ]; then
|
||||
if [ -d "/mnt/hdd/tor" ]; then
|
||||
HiddenServiceDir="/mnt/hdd/tor"
|
||||
else
|
||||
HiddenServiceDir="/var/lib/tor"
|
||||
fi
|
||||
echo "HiddenServiceDir=$HiddenServiceDir" >> $joininConfPath
|
||||
sed -i "s#setupStep=.*#setupStep=3#g" $joininConfPath
|
||||
echo "HiddenServiceDir=$HiddenServiceDir" >>$joininConfPath
|
||||
sed -i "s#setupStep=.*#setupStep=3#g" $joininConfPath
|
||||
fi
|
||||
|
||||
# check for dialog
|
||||
if [ "$(dialog | grep -c "ComeOn Dialog!")" -eq 0 ];then
|
||||
if [ "$(dialog | grep -c "ComeOn Dialog!")" -eq 0 ]; then
|
||||
sudo apt-get install -y dialog
|
||||
fi
|
||||
# check for qrencode
|
||||
if [ "$(qrencode -V 2>&1 | grep -c "not found")" -gt 0 ];then
|
||||
if [ "$(qrencode -V 2>&1 | grep -c "not found")" -gt 0 ]; then
|
||||
sudo apt-get install -y qrencode
|
||||
fi
|
||||
sed -i "s#setupStep=.*#setupStep=4#g" $joininConfPath
|
||||
sed -i "s#setupStep=.*#setupStep=4#g" $joininConfPath
|
||||
|
||||
# check if JoinMarket is installed
|
||||
if [ "${runningEnv}" = raspiblitz ] && [ "$(lsb_release -sc)" = bullseye ]; then
|
||||
# no qtgui for raspibliz on bullseye
|
||||
/home/joinmarket/install.joinmarket.sh -i install -q 0
|
||||
else
|
||||
if [ "${cpu}" = x86_64 ]; then
|
||||
/home/joinmarket/install.joinmarket.sh -i install
|
||||
else
|
||||
# no qtgui on arm
|
||||
/home/joinmarket/install.joinmarket.sh -i install -q 0
|
||||
fi
|
||||
sed -i "s#setupStep=.*#setupStep=5#g" $joininConfPath
|
||||
sed -i "s#setupStep=.*#setupStep=5#g" $joininConfPath
|
||||
fi
|
||||
# change the ssh password if standalone
|
||||
if [ "$runningEnv" = "standalone" ];then
|
||||
if [ "$runningEnv" = "standalone" ]; then
|
||||
source /home/joinmarket/joinin.conf
|
||||
if [ "$setupStep" -lt 6 ];then
|
||||
if [ "$setupStep" -lt 6 ]; then
|
||||
# set ssh passwords on the first run
|
||||
sudo /home/joinmarket/set.password.sh
|
||||
sed -i "s#setupStep=.*#setupStep=6#g" $joininConfPath
|
||||
sed -i "s#setupStep=.*#setupStep=6#g" $joininConfPath
|
||||
fi
|
||||
source /home/joinmarket/joinin.conf
|
||||
if [ "$setupStep" -lt 7 ]&&[ ${cpu} != "x86_64" ];then
|
||||
if [ "$setupStep" -lt 7 ] && [ ${cpu} != "x86_64" ]; then
|
||||
# expand SDcard partition on ARM
|
||||
sudo /home/joinmarket/standalone/expand.rootfs.sh
|
||||
fi
|
||||
fi
|
||||
generateJMconfig
|
||||
sudo sed -i "s#setupStep=.*#setupStep=10#g" $joininConfPath
|
||||
sudo sed -i "s#setupStep=.*#setupStep=10#g" $joininConfPath
|
||||
source /home/joinmarket/joinin.conf
|
||||
if [ "$setupStep" -lt 11 ];then
|
||||
if [ "$runningEnv" = "standalone" ];then
|
||||
if [ "$setupStep" -lt 11 ]; then
|
||||
if [ "$runningEnv" = "standalone" ]; then
|
||||
# open the config menu if standalone
|
||||
/home/joinmarket/menu.config.sh
|
||||
else
|
||||
# setup finished
|
||||
sudo sed -i "s#setupStep=.*#setupStep=100#g" $joininConfPath
|
||||
sudo sed -i "s#setupStep=.*#setupStep=100#g" $joininConfPath
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
|
@ -128,11 +127,11 @@ fi
|
|||
|
||||
# check bitcoind RPC setting
|
||||
# add default value to joinin config if needed
|
||||
if ! grep -Eq "^RPCoverTor=" $joininConfPath;then
|
||||
echo "RPCoverTor=off" >> $joininConfPath
|
||||
if ! grep -Eq "^RPCoverTor=" $joininConfPath; then
|
||||
echo "RPCoverTor=off" >>$joininConfPath
|
||||
fi
|
||||
# check if bitcoin RPC connection is over Tor
|
||||
if grep -Eq "^rpc_host = .*.onion" $JMcfgPath;then
|
||||
if grep -Eq "^rpc_host = .*.onion" $JMcfgPath; then
|
||||
echo "# RPC over Tor is on"
|
||||
sed -i "s/^RPCoverTor=.*/RPCoverTor=on/g" $joininConfPath
|
||||
else
|
||||
|
|
@ -142,14 +141,14 @@ fi
|
|||
|
||||
# check if there is only one joinmarket wallet and make default
|
||||
# add default value to joinin config if needed
|
||||
if ! grep -Eq "^defaultWallet=" $joininConfPath;then
|
||||
echo "defaultWallet=off" >> $joininConfPath
|
||||
if ! grep -Eq "^defaultWallet=" $joininConfPath; then
|
||||
echo "defaultWallet=off" >>$joininConfPath
|
||||
fi
|
||||
if [ "$(ls -p /home/joinmarket/.joinmarket/wallets/ | grep -cv /)" -gt 1 ];then
|
||||
if [ "$(ls -p /home/joinmarket/.joinmarket/wallets/ | grep -cv /)" -gt 1 ]; then
|
||||
echo "# Found more than one wallet file"
|
||||
echo "# Setting defaultWallet to off"
|
||||
sed -i "s#^defaultWallet=.*#defaultWallet=off#g" $joininConfPath
|
||||
elif [ "$(ls -p /home/joinmarket/.joinmarket/wallets/ | grep -cv /)" -eq 1 ];then
|
||||
elif [ "$(ls -p /home/joinmarket/.joinmarket/wallets/ | grep -cv /)" -eq 1 ]; then
|
||||
onlyWallet=$(ls -p /home/joinmarket/.joinmarket/wallets/ | grep -v /)
|
||||
echo "# Found only one wallet file: $onlyWallet"
|
||||
echo "# Using it as default"
|
||||
|
|
@ -157,28 +156,28 @@ elif [ "$(ls -p /home/joinmarket/.joinmarket/wallets/ | grep -cv /)" -eq 1 ];the
|
|||
fi
|
||||
|
||||
# add default value to joinin config if needed
|
||||
if ! grep -Eq "^network=" $joininConfPath;then
|
||||
echo "network=unknown" >> $joininConfPath
|
||||
if ! grep -Eq "^network=" $joininConfPath; then
|
||||
echo "network=unknown" >>$joininConfPath
|
||||
fi
|
||||
isMainnet=$(grep -c "network = mainnet" < $JMcfgPath)
|
||||
isSignet=$(grep -c "network = signet" < $JMcfgPath)
|
||||
isTestnet=$(grep -c "network = testnet" < $JMcfgPath)
|
||||
if [ $isMainnet -gt 0 ];then
|
||||
isMainnet=$(grep -c "network = mainnet" <$JMcfgPath)
|
||||
isSignet=$(grep -c "network = signet" <$JMcfgPath)
|
||||
isTestnet=$(grep -c "network = testnet" <$JMcfgPath)
|
||||
if [ $isMainnet -gt 0 ]; then
|
||||
sed -i "s#^network=.*#network=mainnet#g" $joininConfPath
|
||||
elif [ $isSignet -gt 0 ];then
|
||||
elif [ $isSignet -gt 0 ]; then
|
||||
sed -i "s#^network=.*#network=signet#g" $joininConfPath
|
||||
elif [ $isTestnet -gt 0 ];then
|
||||
elif [ $isTestnet -gt 0 ]; then
|
||||
sed -i "s#^network=.*#network=testnet#g" $joininConfPath
|
||||
else
|
||||
sed -i "s#^network=.*#network=unknown#g" $joininConfPath
|
||||
fi
|
||||
|
||||
# add default value to joinin config if needed
|
||||
if ! grep -Eq "^localip=" $joininConfPath;then
|
||||
echo "localip=unknown" >> $joininConfPath
|
||||
if ! grep -Eq "^localip=" $joininConfPath; then
|
||||
echo "localip=unknown" >>$joininConfPath
|
||||
fi
|
||||
localip=$(hostname -I | awk '{print $1}')
|
||||
sed -i "s#^localip=.*#localip=$localip#g" $joininConfPath
|
||||
|
||||
# change the onion_serving_port if LND is present (avoid collusion with LND REST port)
|
||||
# change the onion_serving_port if LND is present (avoid collision with LND REST port)
|
||||
sed -i "s#^onion_serving_port = 8080#onion_serving_port = 8090#g" $JMcfgPath
|
||||
|
|
|
|||
|
|
@ -43,6 +43,18 @@ Type=simple
|
|||
TimeoutSec=infinity
|
||||
Restart=no
|
||||
|
||||
# Memory limits (DoS / OOM protection)
|
||||
MemoryHigh=300M
|
||||
MemoryMax=512M
|
||||
MemorySwapMax=0
|
||||
|
||||
# Reduce OOM kill priority (lower = less likely to be killed)
|
||||
OOMScoreAdjust=-500
|
||||
OOMPolicy=stop
|
||||
|
||||
# CPU limit
|
||||
CPUQuota=80%
|
||||
|
||||
# Hardening measures
|
||||
PrivateTmp=true
|
||||
ProtectSystem=full
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ fi
|
|||
# Example for commits created on GitHub:
|
||||
# PGPsigner="web-flow"
|
||||
# PGPpubkeyLink="https://github.com/${PGPsigner}.gpg"
|
||||
# PGPpubkeyFingerprint="4AEE18F83AFDEB23"
|
||||
# PGPpubkeyFingerprint="B5690EEEBB952194"
|
||||
|
||||
# Example for commits signed with a personal PGP key:
|
||||
# PGPsigner="janoside"
|
||||
|
|
@ -30,9 +30,18 @@ PGPsigner="$1"
|
|||
PGPpubkeyLink="$2"
|
||||
PGPpubkeyFingerprint="$3"
|
||||
|
||||
wget --prefer-family=ipv4 -O /dev/shm/pgp_keys_${PGPsigner}.asc "${PGPpubkeyLink}"
|
||||
gpg --import --import-options show-only /dev/shm/pgp_keys_${PGPsigner}.asc
|
||||
fingerprint=$(gpg --show-keys /dev/shm/pgp_keys_${PGPsigner}.asc 2>/dev/null | grep "${PGPpubkeyFingerprint}" -c)
|
||||
_temp_dir="$(mktemp -d -p /dev/shm/ 2>/dev/null || mktemp -d)"
|
||||
trap 'rm -rf "$_temp_dir"' EXIT
|
||||
|
||||
keyFile="${_temp_dir}/pgp_keys_${PGPsigner}.asc"
|
||||
rawKeyFile="${keyFile}.raw"
|
||||
|
||||
wget --prefer-family=ipv4 -O "${rawKeyFile}" "${PGPpubkeyLink}"
|
||||
# GitHub can add a Note: armor header when an account key cannot be exported.
|
||||
# GPG imports the key anyway, but prints a misleading "unknown armor header".
|
||||
grep -v '^Note: ' "${rawKeyFile}" >"${keyFile}"
|
||||
gpg --quiet --import --import-options show-only "${keyFile}"
|
||||
fingerprint=$(gpg --show-keys --with-subkey-fingerprint "${keyFile}" 2>/dev/null | tr -d " \t\n\r" | grep "${PGPpubkeyFingerprint}" -c)
|
||||
if [ "${fingerprint}" -lt 1 ]; then
|
||||
echo
|
||||
echo "# WARNING --> the PGP fingerprint is not as expected for ${PGPsigner}" >&2
|
||||
|
|
@ -40,11 +49,9 @@ if [ "${fingerprint}" -lt 1 ]; then
|
|||
echo "# Exiting" >&2
|
||||
exit 7
|
||||
fi
|
||||
gpg --import /dev/shm/pgp_keys_${PGPsigner}.asc
|
||||
rm /dev/shm/pgp_keys_${PGPsigner}.asc
|
||||
gpg --quiet --import "${keyFile}"
|
||||
|
||||
trap 'rm -f "$_temp"' EXIT
|
||||
_temp="$(mktemp -p /dev/shm/)"
|
||||
_temp="${_temp_dir}/git-verify.out"
|
||||
|
||||
if [ $# -eq 3 ] || [ -z "$4" ]; then
|
||||
commitHash="$(git log --oneline | head -1 | awk '{print $1}')"
|
||||
|
|
|
|||
34
test/README.md
Normal file
34
test/README.md
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# JoininBox integration tests
|
||||
|
||||
Run the local Bats suite with:
|
||||
|
||||
```bash
|
||||
test/run-bats-local.sh
|
||||
```
|
||||
|
||||
The descriptor wallet tests require:
|
||||
|
||||
- `bats`
|
||||
- `bitcoind`
|
||||
- `bitcoin-cli`
|
||||
- `curl`
|
||||
- `jq`
|
||||
|
||||
The suite starts its own temporary `bitcoind -regtest` datadir and does not use
|
||||
mainnet, signet, or any existing Bitcoin Core state.
|
||||
|
||||
The `amd64-image-test` workflow downloads a previously built
|
||||
`joininbox-amd64-image-*` artifact, verifies the compressed and raw checksums,
|
||||
decompresses a runner-local qcow2 copy, boots it with QEMU in snapshot mode,
|
||||
copies a pinned `bats-core` checkout into that temporary VM session, and runs
|
||||
the same suite from the JoininBox checkout inside the image. This avoids
|
||||
depending on the guest's configured APT repositories just to install test
|
||||
tooling.
|
||||
|
||||
The test workflow has two entry points:
|
||||
|
||||
- `workflow_run`: runs after a successful `amd64-image-build` once this workflow
|
||||
exists on the repository default branch.
|
||||
- `workflow_dispatch`: reruns against a specific build artifact by providing the
|
||||
`amd64-image-build` workflow run ID, as long as the artifact is still retained
|
||||
by GitHub Actions.
|
||||
214
test/bats/descriptor-wallet.bats
Normal file
214
test/bats/descriptor-wallet.bats
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
#!/usr/bin/env bats
|
||||
|
||||
root_dir="$(cd "$BATS_TEST_DIRNAME/../.." && pwd)"
|
||||
PATH="/home/joinmarket/bitcoin:/usr/local/bin:$PATH"
|
||||
|
||||
require_command() {
|
||||
if ! command -v "$1" >/dev/null 2>&1; then
|
||||
skip "$1 is required"
|
||||
fi
|
||||
}
|
||||
|
||||
setup() {
|
||||
require_command bitcoind
|
||||
require_command bitcoin-cli
|
||||
require_command curl
|
||||
require_command jq
|
||||
|
||||
rpc_user="joininbox"
|
||||
rpc_pass="joininbox"
|
||||
rpc_port="$((20000 + (RANDOM % 20000)))"
|
||||
p2p_port="$((40000 + (RANDOM % 20000)))"
|
||||
bitcoin_datadir="${BATS_TEST_TMPDIR}/bitcoin"
|
||||
joinmarket_cfg="${BATS_TEST_TMPDIR}/joinmarket.cfg"
|
||||
joinin_conf="${BATS_TEST_TMPDIR}/joinin.conf"
|
||||
|
||||
mkdir -p "$bitcoin_datadir"
|
||||
|
||||
bitcoind \
|
||||
-regtest \
|
||||
-datadir="$bitcoin_datadir" \
|
||||
-server \
|
||||
-daemonwait \
|
||||
-rpcuser="$rpc_user" \
|
||||
-rpcpassword="$rpc_pass" \
|
||||
-rpcport="$rpc_port" \
|
||||
-port="$p2p_port" \
|
||||
-fallbackfee=0.0001
|
||||
|
||||
cat >"$joinmarket_cfg" <<EOF
|
||||
rpc_user = $rpc_user
|
||||
rpc_password = $rpc_pass
|
||||
rpc_host = 127.0.0.1
|
||||
rpc_port = $rpc_port
|
||||
rpc_wallet_file = watch-only-descriptor-wallet
|
||||
EOF
|
||||
: >"$joinin_conf"
|
||||
}
|
||||
|
||||
teardown() {
|
||||
if [ -n "${bitcoin_datadir:-}" ] && [ -d "$bitcoin_datadir" ]; then
|
||||
bitcoin-cli \
|
||||
-regtest \
|
||||
-datadir="$bitcoin_datadir" \
|
||||
-rpcuser="$rpc_user" \
|
||||
-rpcpassword="$rpc_pass" \
|
||||
-rpcport="$rpc_port" \
|
||||
stop >/dev/null 2>&1 || true
|
||||
fi
|
||||
}
|
||||
|
||||
load_joininbox_bitcoin_functions() {
|
||||
# shellcheck source=scripts/_functions.bitcoincore.sh
|
||||
# shellcheck disable=SC1091
|
||||
source "$root_dir/scripts/_functions.bitcoincore.sh"
|
||||
# shellcheck disable=SC2034
|
||||
JMcfgPath="$joinmarket_cfg"
|
||||
# shellcheck disable=SC2034
|
||||
joininConfPath="$joinin_conf"
|
||||
|
||||
mktemp() {
|
||||
if [ "${1:-}" = "-p" ] && [ "${2:-}" = "/dev/shm/" ]; then
|
||||
command mktemp "${BATS_TEST_TMPDIR}/joininbox.XXXXXX"
|
||||
else
|
||||
command mktemp "$@"
|
||||
fi
|
||||
}
|
||||
}
|
||||
|
||||
wallet_info() {
|
||||
bitcoin-cli \
|
||||
-regtest \
|
||||
-datadir="$bitcoin_datadir" \
|
||||
-rpcuser="$rpc_user" \
|
||||
-rpcpassword="$rpc_pass" \
|
||||
-rpcport="$rpc_port" \
|
||||
-rpcwallet=watch-only-descriptor-wallet \
|
||||
getwalletinfo
|
||||
}
|
||||
|
||||
check_wallet_migration_with_enter() {
|
||||
printf "\n" | checkWalletMigration
|
||||
}
|
||||
|
||||
check_rpc_wallet_with_enter() {
|
||||
printf "\n" | checkRPCwallet
|
||||
}
|
||||
|
||||
@test "checkRPCwallet creates the configured descriptor watch-only wallet" {
|
||||
load_joininbox_bitcoin_functions
|
||||
|
||||
run checkRPCwallet
|
||||
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"The wallet: watch-only-descriptor-wallet is present and loaded"* ]]
|
||||
|
||||
run wallet_info
|
||||
[ "$status" -eq 0 ]
|
||||
[ "$(jq -r '.descriptors' <<<"$output")" = "true" ]
|
||||
[ "$(jq -r '.private_keys_enabled' <<<"$output")" = "false" ]
|
||||
run grep -q "walletMigrationDone" "$joinin_conf"
|
||||
[ "$status" -ne 0 ]
|
||||
}
|
||||
|
||||
@test "customRPC uses the descriptor wallet RPC endpoint" {
|
||||
bitcoin-cli \
|
||||
-regtest \
|
||||
-datadir="$bitcoin_datadir" \
|
||||
-rpcuser="$rpc_user" \
|
||||
-rpcpassword="$rpc_pass" \
|
||||
-rpcport="$rpc_port" \
|
||||
-named createwallet \
|
||||
wallet_name=watch-only-descriptor-wallet \
|
||||
descriptors=true \
|
||||
disable_private_keys=true >/dev/null
|
||||
|
||||
load_joininbox_bitcoin_functions
|
||||
|
||||
run customRPC "# Wallet info" "getwalletinfo" ""
|
||||
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *'"walletname": "watch-only-descriptor-wallet"'* ]]
|
||||
[[ "$output" == *'"descriptors": true'* ]]
|
||||
[[ "$output" == *'"private_keys_enabled": false'* ]]
|
||||
}
|
||||
|
||||
@test "checkRPCwallet migrates a persisted wallet.dat configuration on Bitcoin Core v30 or later" {
|
||||
bitcoin-cli \
|
||||
-regtest \
|
||||
-datadir="$bitcoin_datadir" \
|
||||
-rpcuser="$rpc_user" \
|
||||
-rpcpassword="$rpc_pass" \
|
||||
-rpcport="$rpc_port" \
|
||||
-named createwallet \
|
||||
wallet_name=wallet.dat \
|
||||
descriptors=true \
|
||||
disable_private_keys=true >/dev/null
|
||||
sed \
|
||||
"s/^rpc_wallet_file =.*/rpc_wallet_file = wallet.dat/" \
|
||||
"$joinmarket_cfg" >"${joinmarket_cfg}.legacy"
|
||||
mv "${joinmarket_cfg}.legacy" "$joinmarket_cfg"
|
||||
|
||||
load_joininbox_bitcoin_functions
|
||||
|
||||
run check_rpc_wallet_with_enter
|
||||
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"Migrating the configured Bitcoin Core wallet"* ]]
|
||||
[[ "$output" == *"WALLET MIGRATION NOTICE"* ]]
|
||||
grep -q "^rpc_wallet_file = watch-only-descriptor-wallet$" "$joinmarket_cfg"
|
||||
grep -q "^walletMigrationDone=true$" "$joinin_conf"
|
||||
|
||||
run wallet_info
|
||||
[ "$status" -eq 0 ]
|
||||
[ "$(jq -r '.descriptors' <<<"$output")" = "true" ]
|
||||
[ "$(jq -r '.private_keys_enabled' <<<"$output")" = "false" ]
|
||||
}
|
||||
|
||||
@test "migrateLegacyRPCWalletConfig keeps wallet.dat on Bitcoin Core v29.2" {
|
||||
sed \
|
||||
"s/^rpc_wallet_file =.*/rpc_wallet_file = wallet.dat/" \
|
||||
"$joinmarket_cfg" >"${joinmarket_cfg}.legacy"
|
||||
mv "${joinmarket_cfg}.legacy" "$joinmarket_cfg"
|
||||
|
||||
load_joininbox_bitcoin_functions
|
||||
getConnectedBitcoinCoreVersion() {
|
||||
echo 290200
|
||||
}
|
||||
getRPC >/dev/null
|
||||
|
||||
run migrateLegacyRPCWalletConfig
|
||||
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"v29.x or earlier; keeping wallet.dat"* ]]
|
||||
grep -q "^rpc_wallet_file = wallet.dat$" "$joinmarket_cfg"
|
||||
}
|
||||
|
||||
@test "checkWalletMigration shows the notice once when wallet.dat exists" {
|
||||
bitcoin-cli \
|
||||
-regtest \
|
||||
-datadir="$bitcoin_datadir" \
|
||||
-rpcuser="$rpc_user" \
|
||||
-rpcpassword="$rpc_pass" \
|
||||
-rpcport="$rpc_port" \
|
||||
-named createwallet \
|
||||
wallet_name=wallet.dat \
|
||||
descriptors=true \
|
||||
disable_private_keys=true >/dev/null
|
||||
|
||||
load_joininbox_bitcoin_functions
|
||||
# shellcheck disable=SC2034
|
||||
rpc_host="127.0.0.1"
|
||||
# shellcheck disable=SC2034
|
||||
rpc_wallet="watch-only-descriptor-wallet"
|
||||
|
||||
run check_wallet_migration_with_enter
|
||||
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"WALLET MIGRATION NOTICE"* ]]
|
||||
grep -q "^walletMigrationDone=true$" "$joinin_conf"
|
||||
|
||||
run checkWalletMigration
|
||||
[ "$status" -eq 0 ]
|
||||
[ "$output" = "" ]
|
||||
}
|
||||
11
test/run-bats-local.sh
Executable file
11
test/run-bats-local.sh
Executable file
|
|
@ -0,0 +1,11 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
if ! command -v bats >/dev/null 2>&1; then
|
||||
echo "bats is required. Install bats-core, then rerun this script." >&2
|
||||
exit 127
|
||||
fi
|
||||
|
||||
bats test/bats
|
||||
|
|
@ -7,4 +7,5 @@
|
|||
[default.extend-words]
|
||||
# don't correct these false positives
|
||||
ba = "ba"
|
||||
ned = "ned"
|
||||
ned = "ned"
|
||||
fpr = "fpr"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue