feat: Bitcoin Core and Electrum servers and wallet

This commit is contained in:
Ben Grande 2024-02-17 00:03:19 +01:00
parent e6fb72c22e
commit dbed18dfa2
148 changed files with 5302 additions and 36 deletions

View File

@ -7,6 +7,34 @@ Files: README.md */README.md docs/* .github/ISSUE_TEMPLATE/*
Copyright: 2023 - 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com> Copyright: 2023 - 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
License: CC-BY-SA-4.0 License: CC-BY-SA-4.0
Files: salt/electrum/files/client/keys/*
Copyright: SomberNight/ghost43 <somber.night@protonmail.com>
Stephan Oeste <stephan@oeste.de>
Thomas Voegtlin <thomasv1@gmx.de>
License: CC0-1.0
Files: salt/sys-bitcoin/files/server/keys/*
Copyright: Ava Chow <me@achow101.com>
Duncan Dean <duncangleeddean@gmail.com>
Gloria Zhao <gloriajzhao@gmail.com>
Hennadii Stepanov (hebasto) <hebasto@gmail.com>
Michael Ford (bitcoin-otc) <fanquake@gmail.com>
Ryan Ofsky <ryan@ofsky.org>
Wladimir J. van der Laan <laanwj@gmail.com>
License: CC0-1.0
Files: salt/sys-electrs/files/server/keys/*
Copyright: Roman Zeyde <roman.zeyde@gmail.com>
License: CC0-1.0
Files: salt/sys-electrumx/files/server/keys/*
Copyright: SomberNight <somber.night@protonmail.com>
License: CC0-1.0
Files: salt/sys-electrumx/files/server/conf/banner.txt
Copyright: Benjamin Grande M. S. <ben.grande.b@gmail.com>
License: CC0-1.0
Files: salt/sys-mirage-firewall/files/admin/mirage-firewall.tar.bz2 Files: salt/sys-mirage-firewall/files/admin/mirage-firewall.tar.bz2
salt/sys-mirage-firewall/files/admin/mirage-firewall.sha256 salt/sys-mirage-firewall/files/admin/mirage-firewall.sha256
salt/sys-mirage-firewall/files/admin/version.txt salt/sys-mirage-firewall/files/admin/version.txt

View File

@ -55,6 +55,9 @@ you accomplish your mission.
- [signal](../salt/signal/README.md) - [signal](../salt/signal/README.md)
- Electronic cash: - Electronic cash:
- [sys-bitcoin](../salt/sys-bitcoin/README.md)
- [sys-electrumx](../salt/sys-electrumx/README.md)
- [sys-electrs](../salt/sys-electrs/README.md)
- [electrum](../salt/electrum/README.md) - [electrum](../salt/electrum/README.md)
### Files ### Files

View File

@ -0,0 +1,14 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
{% if grains['nodename'] != 'dom0' -%}
"{{ slsdotpath }}-set-default-terminal-to-xterm":
cmd.run:
- name: update-alternatives --verbose --set x-terminal-emulator /usr/bin/xterm
- runas: root
{% endif -%}

View File

@ -0,0 +1,9 @@
{#
SPDX-FileCopyrightText: 2023 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
base:
'tpl-dev':
- dev.install-terminal

View File

@ -7,21 +7,34 @@ Electrum Bitcoin Wallet in Qubes OS.
* [Description](#description) * [Description](#description)
* [Installation](#installation) * [Installation](#installation)
* [Usage](#usage) * [Usage](#usage)
* [Wallet cooperation](#wallet-cooperation) * [Connect your cold wallet to a trusted server](#connect-your-cold-wallet-to-a-trusted-server)
* [Connect your cold wallet to an untrusted server](#connect-your-cold-wallet-to-an-untrusted-server)
* [Recommendations for cryptographic operations](#recommendations-for-cryptographic-operations)
* [Cold wallet terminology](#cold-wallet-terminology) * [Cold wallet terminology](#cold-wallet-terminology)
* [Credits](#credits)
## Description ## Description
Setup multiple lightweights Electrum Bitcoin Wallets, one offline qube named Setup multiple lightweights Electrum Bitcoin Wallets, one offline qube named
"electrum-cold" and one online qube based on Whonix-Workstation named "electrum" and one online qube based on Whonix-Workstation named
"electrum-hot". "electrum-hot".
You can use either wallet or both together depending on your setup. Use the
"electrum" to sign transactions and the "electrum-hot" to broadcast them.
By default, the installation verify and fetch the tarball from upstream
sources, avoiding using outdated distribution package versions that lack
important security fixes. The fetching will occur over Tor and on a disposable
qube "disp-electrum-builder", which will then upload the files to the template
"tpl-electrum". The installation on a disposable helps separate the wallet
usage from ever connecting to the internet.
## Installation ## Installation
- Top - Top
```sh ```sh
qubesctl top.enable electrum qubesctl top.enable electrum
qubesctl --targets=tpl-electrum,electrum-cold,electrum-hot state.apply qubesctl --targets=tpl-electrum-builder,tpl-electrum,disp-electrum-builder,electrum,electrum-hot state.apply
qubesctl top.disable electrum qubesctl top.disable electrum
qubesctl state.apply electrum.appmenus qubesctl state.apply electrum.appmenus
``` ```
@ -30,34 +43,122 @@ qubesctl state.apply electrum.appmenus
<!-- pkg:begin:post-install --> <!-- pkg:begin:post-install -->
```sh ```sh
qubesctl state.apply electrum.create qubesctl state.apply electrum.create
qubesctl --skip-dom0 --targets=tpl-electrum-builder state.apply electrum.install-builder
qubesctl --skip-dom0 --targets=tpl-electrum state.apply electrum.install qubesctl --skip-dom0 --targets=tpl-electrum state.apply electrum.install
qubesctl --skip-dom0 --targets=electrum-cold,electrum-hot state.apply electrum.configure qubesctl --skip-dom0 --targets=disp-electrum-builder state.apply electrum.configure-builder
qubesctl --skip-dom0 --targets=electrum state.apply electrum.configure
qubesctl --skip-dom0 --targets=electrum-hot state.apply electrum.configure-hot
qubesctl state.apply electrum.appmenus qubesctl state.apply electrum.appmenus
``` ```
<!-- pkg:end:post-install --> <!-- pkg:end:post-install -->
## Usage ## Usage
The qube `electrum-cold` serves as a cold wallet, while the `electrum-hot` is The qube `electrum` serves as a cold wallet, while the `electrum-hot` is
networked via tor and you can use it as a watching-only (only pub key present) networked via tor. Both wallets can be watching-only or signing wallet,
or hot wallet (private key present). depending on how you configure them.
### Wallet cooperation ### Connect your cold wallet to a trusted server
If you plan to create private keys on any wallet, it is recommended to pause If you are running an Electrum Server with our formulas, such as
or shutdown all qubes to reduce the side-channel attack surface. [sys-electrs](../sys-electrs/README.md),
[sys-electrumx](../sys-electrumx/README.md), the formula documentation
instructs how to make the server available to the client and the rest of this
section doesn't apply to you.
As you have both types of wallets, a networked and an offline one, with the If you server doesn't run with our formulas, you must do some extra steps.
networked wallet you can broadcast transactions while with the offline one,
you sign them. Sharing data between the qubes can be done with `qvm-copy` and Choose a netvm that can reach your Electrum Server and bind the server port to
the process of combining a watching-only and a cold wallet is explained in the the netvm localhost. Prefer the port that supports **SSL**, normally `50002`.
[Electrum wiki](https://electrum.readthedocs.io/en/latest/coldstorage.html). In the following example, our server is running on `192.168.2.10:50002` and
our netvm qube is named `sys-net`.
In the qube `dom0`, allow `electrum` to connect to `sys-net` port
`50002` via Qrexec Policy in the file `/etc/qubes/policy.d/30-user.policy`:
```qrexecpolicy
qubes.ConnectTCP +50002 electrum @default allow target=sys-net
```
In the qube `sys-net`, add the `socat` command to the file
`/rw/config/rc.local`:
```sh
socat TCP4-LISTEN:50002,reuseaddr,fork,bind=127.0.0.1 TCP:192.168.2.10:50002 &
```
In the qube `electrum`, add the `qvm-connect-tcp` command to the file
`/rw/config/rc.local`:
```sh
qvm-connnect-tcp ::50002
```
In the qube `electrum`, run as the user `user` the electrum configuration
commands:
```sh
electrum --offline setconfig auto_connect false
electrum --offline setconfig oneserver true
electrum --offline setconfig server 127.0.0.1:50002
```
If you used a plain-text port, no SSL:
```sh
electrum --offline setconfig server 127.0.0.1:50001:t
```
### Connect your cold wallet to an untrusted server
You should not use an untrusted third-party Electrum Server with this method
because it only connects to a single server and it poses a higher security
risk as the SPV method can not work with this design. If you don't have your
own server, you are better off using `electrum-hot` and connecting to multiple
public servers, you loose privacy (over Tor) in favor of security (no loss of
Bitcoins).
As the client can't connect to other services to subscribe to block header
notifications, the wallet is solely trusting the information delivered by the
third-party server, whether its is lagging, splitting or forking the chain.
The SPV method can not be executed because it does not have a minimum number
of servers to verify the information against each other.
Read more about [potention SPV weaknessses](https://developer.bitcoin.org/devguide/operating_modes.html#potential-spv-weaknesses).
### Recommendations for cryptographic operations
If you plan to create private keys or sign transaction, it is recommended to
pause or shutdown all qubes to reduce the side-channel attack surface.
Although there is a possibility that there is not enough entropy source to
create a secure wallet in a virtualized environment, this property is not
taken care by this formula, it trusts the Kernel and Electrum Wallet to
provide enough entropy.
### Cold wallet terminology ### Cold wallet terminology
I can expect some comments complaining about the term `cold wallet` when I can expect some comments complaining about the term `cold wallet` when
using Qubes OS with an online system. We use this term to refer to an isolated using Qubes OS with an online system. We use this term to refer to an isolated
environment (a qube) that has no internet connection. environment (a qube) that has no internet connection and can optionally reach
an Electrum Server.
As a general rule, private keys should be stored on cold (offline) storage,
because it greatly diminishes the attack surface of internet facing malware.
Should you decide to store the private key on a cold virtualized storage such
as the `electrum` non-networked qube while other qubes have internet
access or on a physically isolated machine normally referred as an `air
gapped` system, every method has drawbacks.
As you have both types of wallets, a networked `electrum-hot` and an offline
one `electrum`, with the networked wallet you can broadcast transactions
while with the offline one, you sign them. Sharing data between the qubes can
be done with `qvm-copy` and the process of combining a watching-only and a
cold wallet is explained in the [Electrum wiki](https://electrum.readthedocs.io/en/latest/coldstorage.html).
Apart from the fact that most people loose Bitcoin by loosing their private
keys, being phished, using modified or outdated Bitcoin Node versions, the
difficult part of securing your private key on a separate domain compared to
the domain that can broadcast the transaction, is the trust you must assign to
the less trusted domain to be able to send information to the more trusted
domain. Such things are much worse when using non-Qubes because the transfer
method is often insecure.
You are free to use a non-Qubes physically air-gapped system if you prefer, You are free to use a non-Qubes physically air-gapped system if you prefer,
you just have to remove the Audio stack (microphone, speakers), Video stack you just have to remove the Audio stack (microphone, speakers), Video stack
@ -70,6 +171,13 @@ exposes to the USB stack, transfer via radio exposes all devices nearby to the
signal being passed, guard against supply-chain attacks. In the end, your signal being passed, guard against supply-chain attacks. In the end, your
air-gapped system is not so secure as you thought it to be. air-gapped system is not so secure as you thought it to be.
QubesOS provides secure tools to communicate data between domains, most common
ones are inter-VM File Copy and inter-VM clipboard. When using those programs,
there is no USB, nor camera, nor radio signal used in those qubes, therefore
not dealing with a lot of complicated and code that could expose higher risks
or normal systems, but isolated on Qubes by UsbVMs, that holds the backend of
the USB PCI bus devices.
Yes, a Xen exploit that reaches Dom0 or a CPU exploit that can infer Yes, a Xen exploit that reaches Dom0 or a CPU exploit that can infer
[the memory contents of other running VMs](https://www.qubes-os.org/news/2023/11/14/qsb-096/) [the memory contents of other running VMs](https://www.qubes-os.org/news/2023/11/14/qsb-096/)
or [the contents of data from a different execution context on the or [the contents of data from a different execution context on the
@ -82,5 +190,12 @@ but then again, transferring the data safely to communicate with a networked
device for the transactions to be broadcasted is still a hard thing to fix for device for the transactions to be broadcasted is still a hard thing to fix for
physical air-gapped systems. physical air-gapped systems.
We recommend reading former QubesOS developer, Joanna Rutkowska's paper about
[Software compartmentalization vs physical separation](https://invisiblethingslab.com/resources/2014/Software_compartmentalization_vs_physical_separation.pdf).
There is no consensus on the best solution, choose the option that you can There is no consensus on the best solution, choose the option that you can
have more security, not the one you "fell" more secure. have more security, not the one you "fell" more secure.
## Credits
- [qubenix](https://github.com/qubenix/qubes-whonix-bitcoin)

View File

@ -5,4 +5,5 @@ SPDX-License-Identifier: AGPL-3.0-or-later
#} #}
{% from 'utils/macros/clone-template.sls' import clone_template -%} {% from 'utils/macros/clone-template.sls' import clone_template -%}
{{ clone_template('debian-minimal', sls_path) }} {{ clone_template(['debian-minimal', 'whonix-workstation'], sls_path) }}
{{ clone_template('whonix-workstation', 'electrum-builder', include_create=False) }}

View File

@ -0,0 +1,122 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
{% if grains['nodename'] != 'dom0' -%}
include:
- dev.home-cleanup
- dotfiles.copy-x11
- dotfiles.copy-sh
## https://download.electrum.org/VERSION/Electrum-VERSION.tar.gz(.asc)
{% set electrum_version = '4.5.2' -%}
{% set electrum_url_dir = 'https://download.electrum.org/' ~ electrum_version ~ '/' -%}
{% set electrum_archive_dir = 'Electrum-' ~ electrum_version -%}
{% set electrum_file_archive = electrum_archive_dir ~ '.tar.gz' -%}
{% set electrum_file_sig = electrum_file_archive ~ '.asc' -%}
{% set electrum_url_archive = electrum_url_dir ~ electrum_file_archive -%}
{% set electrum_url_sig = electrum_url_dir ~ electrum_file_sig -%}
"{{ slsdotpath }}-gnupg-home":
file.directory:
- name: /home/user/.gnupg/electrum
- user: user
- group: user
- mode: '0700'
- makedirs: True
"{{ slsdotpath }}-save-keys":
file.recurse:
- require:
- file: "{{ slsdotpath }}-gnupg-home"
- name: /home/user/.gnupg/electrum/download/
- source: salt://{{ slsdotpath }}/files/client/keys/
- user: user
- group: user
- file_mode: '0600'
- dir_mode: '0700'
- makedirs: True
"{{ slsdotpath }}-import-keys":
cmd.run:
- require:
- file: "{{ slsdotpath }}-save-keys"
- name: gpg --status-fd=2 --homedir . --import download/*.asc
- cwd: /home/user/.gnupg/electrum
- runas: user
- success_stderr: IMPORT_OK
"{{ slsdotpath }}-import-ownertrust":
cmd.run:
- require:
- cmd: "{{ slsdotpath }}-import-keys"
- name: gpg --homedir . --import-ownertrust download/otrust.txt
- cwd: /home/user/.gnupg/electrum
- runas: user
"{{ slsdotpath }}-remove-failed-download-or-verification":
file.absent:
- name: /tmp/electrum-download
- onfail:
- cmd: "{{ slsdotpath }}-download"
- cmd: "{{ slsdotpath }}-gpg-verify"
"{{ slsdotpath }}-make-download-dir":
file.directory:
- name: /tmp/electrum-download
- mode: '0755'
- user: user
- group: user
- makedirs: True
## file.managed does not fetch URLs through a SocksProxy.
"{{ slsdotpath }}-download":
cmd.run:
- require:
- file: "{{ slsdotpath }}-make-download-dir"
- name: |
timeout --foreground 1200 curl.anondist-orig \
--connect-timeout 60 \
--tlsv1.3 --proto =https \
--fail --fail-early \
--proxy "socks5h://10.152.152.10:9400" \
--parallel --parallel-immediate \
--no-progress-meter --silent --show-error \
-O "{{ electrum_url_archive }}" \
-O "{{ electrum_url_sig }}"
- cwd: /tmp/electrum-download
- runas: user
"{{ slsdotpath }}-gpg-verify":
cmd.run:
- require:
- cmd: "{{ slsdotpath }}-download"
- cmd: "{{ slsdotpath }}-import-ownertrust"
## Multiple detached signatures has bad UX with GPG.
- env:
- GNUPGHOME: /home/user/.gnupg/electrum/
- name: gpg --status-fd=2 --verify "{{ electrum_file_sig }}"
- cwd: /tmp/electrum-download
- runas: user
"{{ slsdotpath }}-extract-archive":
archive.extracted:
- require:
- cmd: "{{ slsdotpath }}-gpg-verify"
- name: /tmp/
- source: /tmp/electrum-download/{{ electrum_file_archive }}
- overwrite: True
- clean: True
"{{ slsdotpath }}-copy-files-to-template":
cmd.run:
- require:
- archive: "{{ slsdotpath }}-extract-archive"
- name: qrexec-client-vm -T -- @default qusal.InstallElectrum /usr/lib/qubes/qfile-agent electrum/ run_electrum electrum.desktop
- cwd: /tmp/{{ electrum_archive_dir }}
- runas: user
{% endif -%}

View File

@ -0,0 +1,9 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
base:
'disp-electrum-builder':
- electrum.configure-builder

View File

@ -0,0 +1,19 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
{% if grains['nodename'] != 'dom0' -%}
include:
- dev.home-cleanup
- dotfiles.copy-x11
- dotfiles.copy-sh
"{{ slsdotpath }}-setconfig-check_updates":
cmd.run:
- name: electrum --offline setconfig check_updates false
- runas: user
{% endif -%}

View File

@ -0,0 +1,9 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
base:
'electrum-hot':
- electrum.configure-hot

View File

@ -10,11 +10,7 @@ include:
- dev.home-cleanup - dev.home-cleanup
- dotfiles.copy-x11 - dotfiles.copy-x11
- dotfiles.copy-sh - dotfiles.copy-sh
- whonix-workstation.configure-offline
"{{ slsdotpath }}-setconfig-auto_connect":
cmd.run:
- name: electrum --offline setconfig auto_connect false
- runas: user
"{{ slsdotpath }}-setconfig-check_updates": "{{ slsdotpath }}-setconfig-check_updates":
cmd.run: cmd.run:

View File

@ -6,5 +6,4 @@ SPDX-License-Identifier: AGPL-3.0-or-later
base: base:
'electrum': 'electrum':
- match: nodegroup
- electrum.configure - electrum.configure

View File

@ -6,11 +6,11 @@ SPDX-License-Identifier: AGPL-3.0-or-later
{%- from "qvm/template.jinja" import load -%} {%- from "qvm/template.jinja" import load -%}
{%- import "whonix/template.jinja" as whonix -%} {%- import "whonix-workstation/template.jinja" as whonix_workstation -%}
include: include:
- .clone - .clone
- whonix.create - sys-bitcoin.create
{% load_yaml as defaults -%} {% load_yaml as defaults -%}
name: tpl-{{ slsdotpath }} name: tpl-{{ slsdotpath }}
@ -26,7 +26,23 @@ features:
{{ load(defaults) }} {{ load(defaults) }}
{% load_yaml as defaults -%} {% load_yaml as defaults -%}
name: {{ slsdotpath }}-cold name: tpl-{{ slsdotpath }}-builder
force: True
require:
- sls: {{ slsdotpath }}.clone
prefs:
- audiovm: ""
- default_dispvm: ""
tags:
- add:
- "updatevm-sys-bitcoin-gateway"
- del:
- "whonix-updatevm"
{%- endload %}
{{ load(defaults) }}
{% load_yaml as defaults -%}
name: {{ slsdotpath }}
force: True force: True
require: require:
- sls: {{ slsdotpath }}.clone - sls: {{ slsdotpath }}.clone
@ -48,7 +64,10 @@ features:
- service.cups - service.cups
- service.cups-browsed - service.cups-browsed
- set: - set:
- menu-items: "qubes-run-terminal.desktop qubes-start.desktop electrum.desktop" - menu-items: "qubes-run-terminal.desktop qubes-start.desktop qubes-open-file-manager.desktop electrum.desktop"
tags:
- add:
- "electrum-client"
{%- endload %} {%- endload %}
{{ load(defaults) }} {{ load(defaults) }}
@ -58,25 +77,92 @@ force: True
require: require:
- sls: {{ slsdotpath }}.clone - sls: {{ slsdotpath }}.clone
present: present:
- template: {{ whonix.whonix_workstation_template }} - template: {{ whonix_workstation.template }}
- label: orange - label: orange
prefs: prefs:
- template: {{ whonix.whonix_workstation_template }} - template: {{ whonix_workstation.template }}
- label: orange - label: orange
- audiovm: "" - audiovm: ""
- netvm: sys-bitcoin-gateway
- vcpus: 1 - vcpus: 1
- memory: 400 - memory: 400
- maxmem: 600 - maxmem: 600
- autostart: False - autostart: False
- include_in_backups: True - include_in_backups: True
tags:
- add:
- anon-vm
features: features:
- disable: - disable:
- service.cups - service.cups
- service.cups-browsed - service.cups-browsed
- set: - set:
- menu-items: "qubes-run-terminal.desktop qubes-start.desktop qubes-open-file-manager.desktop electrum.desktop" - menu-items: "qubes-run-terminal.desktop qubes-start.desktop qubes-open-file-manager.desktop electrum.desktop"
tags:
- add:
- "anon-vm"
{%- endload %} {%- endload %}
{{ load(defaults) }} {{ load(defaults) }}
{% load_yaml as defaults -%}
name: dvm-electrum-builder
force: True
require:
- qvm: tpl-electrum-builder
present:
- template: tpl-electrum-builder
- label: red
prefs:
- template: tpl-electrum-builder
- label: red
- netvm: sys-bitcoin-gateway
- audiovm: ""
- default_dispvm: ""
- vcpus: 4
- memory: 400
- maxmem: 2000
- autostart: False
- template_for_dispvms: True
features:
- disable:
- service.cups
- service.cups-browsed
tags:
- add:
- "anon-bitcoin-vm"
- del:
- "anon-vm"
{%- endload %}
{{ load(defaults) }}
{% load_yaml as defaults -%}
name: disp-electrum-builder
force: True
require:
- qvm: dvm-electrum-builder
present:
- template: dvm-electrum-builder
- label: red
- class: DispVM
prefs:
- template: dvm-electrum-builder
- label: red
- netvm: sys-bitcoin-gateway
- audiovm: ""
- vcpus: 4
- memory: 400
- maxmem: 2000
- autostart: False
- include_in_backups: False
features:
- disable:
- appmenus-dispvm
- service.cups
- service.cups-browsed
tags:
- add:
- "anon-bitcoin-vm"
- del:
- "anon-vm"
{%- endload %}
{{ load(defaults) }}
{% from 'utils/macros/policy.sls' import policy_set with context -%}
{{ policy_set(sls_path, '80') }}

View File

@ -0,0 +1,12 @@
# SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
## Do not modify this file, create a new policy with with a lower number in the
## file name instead. For example `30-user.policy`.
qusal.InstallElectrum * disp-electrum-builder @default allow target=tpl-electrum user=root autostart=yes
qusal.InstallElectrum * @anyvm @anyvm deny
qubes.ConnectTCP +50001 @tag:electrum-client @tag:bitcoin-client allow
qubes.ConnectTCP * @tag:electrum-client @anyvm deny
## vim:ft=qrexecpolicy

View File

@ -0,0 +1,54 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBGDI71QBEACpSQg2/ZronvXY/Jhe9N2vfasExcVGEfBX0P6IqUGy/WTERmxr
HN+D4wRXqUtVCE2phLfDmQPR7vJZBlULQg6pviraTRlYchlUvvAqNBl/crS6Ms8d
ytFvhMvBPyePfTsy4xeDz7I4my9dpndcdONPJkxzFs77nqe/2RO78ELTtyRvOW1s
Ll6b7lCinPZ65IOWwqWfIplxEWzNUMJn45Ay5Qhu+pgBn6076W06Sgc4nUSFROXn
umTF9wqtQGl/A6cd3ZKwh1Ypo4BgglUmPJHXm3AZ9jMlPPlNMdVdffBoD2JJg+DY
2hAmlzduLNJ1Q4takn+4ZWuTvrRtLROtGZkxltxacNK4nRPz17XWe52YjpvxsODc
QFxxjPfd4HF6qnO8Fni+cn6BrIo62s/AsLQ26/OtTLO+Tx5w1ch0uKUBHdZEfFbG
S9vXI+So2EJxo48WlyN62B5MqC8GYZnz3/zW543E6/3uB8SIvsp3Dm7SxID8vBYi
1IUmCT+Tm5VNVatILiluHc/LVWfMDo0WSCpw5WRwEqgkquRwJ56X1XKta4YSXqqt
aDubWgR9i/m4hdik/caQJwLuoZj0aZMB8dIoZLpG6ZbqLLivjRFqWlWbMQDKkHP6
qTxKZRFUyfAXUkyvjlDioxATFnFOQ2keqoFpFL1P2LeiplbiIiQeaLPeSwARAQAB
tFBTb21iZXJOaWdodC9naG9zdDQzIChFbGVjdHJ1bSBSRUxFQVNFIHNpZ25pbmcg
a2V5KSA8c29tYmVyLm5pZ2h0QHByb3Rvbm1haWwuY29tPokCTgQTAQgAOBYhBA7t
z9XK+0WQZzSbI8qe7sQ9+RHcBQJgyPIBAhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4B
AheAAAoJEMqe7sQ9+RHcFYsP/R2boaEfx22rwVjqxKlPbLD7Ruc6D5d7i9Zy/pAd
oM5w7PKK9HQUzgRrqcvnIhA/Tq/sdpKTMrfKjRpEUKESIFi7aXkcfk8EvFq/sAIw
5ukbQCKiZr/jNNygG2RZTI4BCs6SabRmUt4O48glUC2hBUIUsyRyQSJ6gE3iwHhb
nepOItftoOnze+zpEgduhMi0OxQsUrnvd2XMhHd5DCb4rgIH+4Bf4QwcbDf2zdXU
brM6xRlL/oAV5qjytXY6g5hrYLm1tVgY9Qu0N3PyAiuXbl04P5DPwa29YVay4kCf
4J9jOR/2+fnZVa3lrgGluLqmQL3PFxzbp5DPX1oP3K+h1RC6nllgFBaBPY9IRgi4
HcxdqCk13E6Ev1B31HyzCFryLeiJ2DljiVRxfxcqVRI2vmbLIFQ8yGx34ONZS/kl
QBTZQx4jZ8DKmb1A+E1aExHCgb0ON2IZrKtPqqrEkr9SM2MTuIcgzVAphUsB9E7x
PvxNeLc/Mh0h6owilMVwnZgbaLCTBnrqzzrduv9QjNfB/cBpyZGYwmpm+FNuzCk6
w+wyJ5A0WuEyqwKfegt66WDstZCzD+gvundIBjAJzyex6xLkSXZmgrHO9eYJxvMe
ZJkImX/Rpq3/zYsdVdoI4Zyguv5ExLzDJrEZdoyJO/NZ5IK2+ac9abndtl7sPa3C
6AVniQJKBBABCAA0FiEEStZDOd+gXiCz9q1R57dIza9eXtkFAmDI8qwWFIAAAAAA
DQAAcmVtQGdudXBnLm9yZwAKCRDnt0jNr15e2Yd9D/9PYFEGWyxNmtCAAvSs7UzU
z161lgNo6Ldi5VZcieADZ5f9DAadvk8F7NE/klU8FulToV6o+eJy24Mip44cdQGv
glw7X0mQVlUHS5bIzlXHXTFAJcBgw1RDOFOP1Zz9CnbiYAaT/yQqxxpqDt2/RmPk
wdxpTwdhNDYqSEGe3eq52L+FxNNlx7TKN4LMA3MVnmyXB4u/cEQd2v9gGoGUMQkt
GnxyuJO8RRZZsOpK13ZZSpb2adW58t6xqptvdPkfLtPOeyeXyKfOOJgZ54e19u09
WS5RFtccEIzddp0E6G7SORWY/q33LOQaZpxfUnickdu1ca72ZveBCSMg+ckFnUyS
Q36Mrj6bVx4Zu/ke4ilGFtnNYbqdd6NGFE2gqcegvpp+Wsfe20/P/gjYDVafIGQc
a78HRPNIGY2Kg7s/ap6d8fHveDZM5kKpxtNP0ljDSKsLdBqqLqExnab3aSao9L7C
VH09fBaMeBjUzRl0yDkW6N2cCJucLWoBoCmL7LsZc37j/fpMKD/zE8P154wzWcyc
nsdrtU13qk2Nw4S0gfpBm4nDd8mjVV/xt3Qk4A7L6YACXKf17hmaVR0U0RpvNyMi
eGDE4YSnJ5U0KXwgIBkBQCwx5FfLeatD0gxCZQaBe0ul3GZ0JmXWOzTt2xTzjmrG
7VcQnGg4LAOaYrlV6FJHLokCMwQQAQoAHRYhBGaU2N576O5WMb7ZUCvVgkt/lHDm
BQJgygHkAAoJECvVgkt/lHDmCzcP/3rX4ltWaAYbCH7tvgel4ti1NwAAgkmNpzUz
ny2BDTJnwaydgzCQ3+wah0wTWQBzHCoD+RLsS3EKCnfK8X4MaQ5vyNPkg8jautRX
9dn2v+F5y3/y+8cXBfWl3HG4hHqvr9XZXWfdiTSM9XA8Tozrqigd8lPMeIsWTnuU
44CL0H4wwT9ncA24cbLaSu26zdISVoPJbxrsNZu+iA/uwVNH7HjKrd6vY7F/l+WY
Vxl5ryjK87b2I6vzH9/oy9MNKZAtPVbtSTp5WuYKwexe+UE9ThiMty92xbnAleJL
FlwcHViBBCqGU8g2+ZNYfh1QQRrAR3mEH73ZJNicUny2/2zX/v0zyfR3GJVpO2zn
7zSZn6UYNOdkWCJfZIoNGdKfMOCfMFnE/Nw1+wlohpcm/2/o7zdJjyyHWk2xySBx
BOvZisM5FOQCiZGxWsBfrFPRcQ6E3l5x/JTxLdCrCjXBZAT6FZwa6Nco7zgnY2nr
kcFbMaOGBUJ0S3cDe2GDYOPYs9TXii4RmT5WUJsLbrCanoltMYr5m7/SFuCjFaJc
I7adkKYEeoOi6AZgiPz0J+MZuGN+Goyhx0eoDzIG8+QPPvssPvzF4hNTua2MRe5B
/wbNkSbv2eGgFlTPhxBDZzwA3Kk5mnF3YZfBZzA7lyLUm97IaRW+ipwmugOIgEJy
0GZsSaso
=zSe2
-----END PGP PUBLIC KEY BLOCK-----

View File

@ -0,0 +1,76 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
=sUYl
-----END PGP PUBLIC KEY BLOCK-----

View File

@ -0,0 +1,263 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
=qsoI
-----END PGP PUBLIC KEY BLOCK-----

View File

@ -0,0 +1,5 @@
# List of assigned trustvalues, created Thu 02 Nov 2023 09:43:48 PM UTC
# (Use "gpg --import-ownertrust" to restore them)
0EEDCFD5CAFB459067349B23CA9EEEC43DF911DC:6:
6694D8DE7BE8EE5631BED9502BD5824B7F9470E6:6:
9EDAFF80E080659604F4A76B2EBB056FD847F8A7:6:

View File

@ -0,0 +1,22 @@
#!/bin/sh
## SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
##
## SPDX-License-Identifier: AGPL-3.0-or-later
set -eu
python_dir="/usr/lib/python3/dist-packages"
bin_dir="/usr/bin"
app_dir="/usr/share/applications"
tmp_dir="/tmp/electrum-upload"
rm -rf "${tmp_dir}"
mkdir -p "${tmp_dir}"
qfile-unpacker 0 "${tmp_dir}"
cd "${tmp_dir}"
cp -r electrum "${python_dir}"/
cp electrum.desktop "${app_dir}"/
cp run_electrum "${bin_dir}"/electrum
## Qube needs to shutdown for the app qube to have the uploaded files.
shutdown now

View File

@ -8,7 +8,13 @@ base:
'dom0': 'dom0':
- match: nodegroup - match: nodegroup
- electrum.create - electrum.create
'tpl-electrum-builder':
- electrum.install-builder
'tpl-electrum': 'tpl-electrum':
- electrum.install - electrum.install
'electrum-cold,electrum-hot': 'disp-electrum-builder':
- electrum.configure-builder
'electrum':
- electrum.configure - electrum.configure
'electrum-hot':
- electrum.configure-hot

View File

@ -0,0 +1,32 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
{% if grains['nodename'] != 'dom0' -%}
include:
- dev.home-cleanup
- dotfiles.copy-sh
- dotfiles.copy-x11
- sys-pgp.install-client
"{{ slsdotpath }}-builder-updated":
pkg.uptodate:
- refresh: True
"{{ slsdotpath }}-builder-installed":
pkg.installed:
- require:
- pkg: "{{ slsdotpath }}-builder-updated"
- refresh: True
- install_recommends: False
- skip_suggestions: True
- pkgs:
- qubes-core-agent-networking
- ca-certificates
- curl
- tar
{% endif -%}

View File

@ -0,0 +1,9 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
base:
'tpl-electrum-builder':
- electrum.install-builder

View File

@ -0,0 +1,27 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
{% if grains['nodename'] != 'dom0' -%}
include:
- dev.home-cleanup
- dotfiles.copy-sh
- dotfiles.copy-x11
"{{ slsdotpath }}-distro-updated":
pkg.uptodate:
- refresh: True
"{{ slsdotpath }}-distro-installed":
pkg.installed:
- refresh: True
- install_recommends: False
- skip_suggestions: True
- pkgs:
- electrum
- python3-pyqt5
{% endif -%}

View File

@ -0,0 +1,9 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
base:
'tpl-electrum':
- electrum.install-distro

View File

@ -15,13 +15,50 @@ include:
pkg.uptodate: pkg.uptodate:
- refresh: True - refresh: True
"{{ slsdotpath }}-remove-distro-package":
pkg.removed:
- pkgs:
- electrum
- python3-electrum
"{{ slsdotpath }}-installed": "{{ slsdotpath }}-installed":
pkg.installed: pkg.installed:
- require:
- pkg: "{{ slsdotpath }}-remove-distro-package"
- pkg: "{{ slsdotpath }}-updated"
- refresh: True - refresh: True
- install_recommends: False - install_recommends: False
- skip_suggestions: True - skip_suggestions: True
- pkgs: - pkgs:
- electrum ## Unlisted dependency.
- python3-jsonpatch
## Dependencies retrieved from 'electrum' and 'python3-electrum' pkg.
- python3-pyqt5 - python3-pyqt5
- libjs-jquery
- libjs-jquery-ui
- libjs-jquery-ui-theme-ui-lightness
- libsecp256k1-1
- node-qrcode-generator
- python3-cryptography
- python3-distutils
- python3-aiohttp
- python3-aiohttp-socks
- python3-aiorpcx
- python3-attr
- python3-bitstring
- python3-certifi
- python3-dnspython
- python3-protobuf
- python3-qrcode
"{{ slsdotpath }}-rpc":
file.recurse:
- name: /etc/qubes-rpc/
- source: salt://{{ slsdotpath }}/files/client/rpc/
- user: root
- group: root
- file_mode: '0755'
- dir_mode: '0755'
- makedirs: True
{% endif -%} {% endif -%}

230
salt/sys-bitcoin/README.md Normal file
View File

@ -0,0 +1,230 @@
# sys-bitcoin
Bitcoin Core in Qubes OS.
## Table of Contents
* [Description](#description)
* [Installation](#installation)
* [Usage](#usage)
* [Custom daemon parameters](#custom-daemon-parameters)
* [Bitcoin Core GUI](#bitcoin-core-gui)
* [Connect to a remote Bitcoin RPC](#connect-to-a-remote-bitcoin-rpc)
* [Evaluation of remote Bitcoin RPC](#evaluation-of-remote-bitcoin-rpc)
* [Configure the remote node](#configure-the-remote-node)
* [Connect the qube to the remote node](#connect-the-qube-to-the-remote-node)
* [Database on external drive](#database-on-external-drive)
* [Credits](#credits)
## Description
Setup a Bitcoin Daemon full-node qube named "sys-bitcoin", where you will
index the Bitcoin blockchain. A second non-networked qube named "bitcoin" can
manage a wallet and sign transactions.
By default, installation from upstream binaries will be used, but you can
choose to build from source if you prefer. Compiling from source will not have
the default configuration flags, but will be optimized to our use case.
The download of the Bitcoin source code or binaries as well as the connections
to the Bitcoin P2P network will happen over the Tor network.
If you already have a node on your network that has indexed the blockchain
already and has RPC enabled for remote clients, you can also connect to it,
preferably if it has transport encryption when connecting to the Bitcoin node
with an encrypted tunnel.
A disposable qube "disp-bitcoin-builder" will be created, based on
Whonix-Workstation, it will server to install and verify Bitcoin Core. After
the verification succeeds, files are copied to the template "tpl-sys-bitcoin".
This method was chosen so the client can be always offline and the build
artifacts are built on a machine that is not running the daemon and thus can
be copied to the template with a higher degree of trust.
At least `1TB` of disk space is required. At block `829054` (2024-02-05),
`642G` are used.
## Installation
- Top
```sh
qubesctl top.enable sys-bitcoin
qubesctl --targets=sys-bitcoin-gateway,tpl-sys-bitcoin,disp-sys-bitcoin-builder,sys-bitcoin,bitcoin state.apply
qubesctl top.disable sys-bitcoin
qubesctl state.apply sys-bitcoin.appmenus
```
- State
<!-- pkg:begin:post-install -->
```sh
qubesctl state.apply sys-bitcoin.create
qubesctl --skip-dom0 --targets=sys-bitcoin-gateway state.apply sys-bitcoin.configure-gateway
qubesctl --skip-dom0 --targets=tpl-sys-bitcoin state.apply sys-bitcoin.install
qubesctl --skip-dom0 --targets=disp-bitcoin-builder state.apply sys-bitcoin.configure-builder
qubesctl --skip-dom0 --targets=sys-bitcoin state.apply sys-bitcoin.configure
qubesctl --skip-dom0 --targets=bitcoin state.apply sys-bitcoin.configure-client
qubesctl state.apply sys-bitcoin.appmenus
```
<!-- pkg:end:post-install -->
If you prefer to build from source (will take approximately 1 hour to build):
```sh
qubesctl --skip-dom0 --targets=tpl-sys-bitcoin state.apply sys-bitcoin.install-source
qubesctl --skip-dom0 --targets=disp-bitcoin-builder state.apply sys-bitcoin.configure-builder-source
```
If you want to relay blocks (listening node):
```sh
qubesctl --skip-dom0 --targets=sys-bitcoin-gateway state.apply sys-bitcoin.configure-gateway-listen
qubesctl --skip-dom0 --targets=sys-bitcoin state.apply sys-bitcoin.configure-listen
```
Add the tag `bitcoin-client` to the client and install in the client template:
```sh
qubesctl --skip-dom0 --targets=tpl-QUBE state.apply sys-bitcoin.install-client
```
## Usage
The qube `sys-bitcoin` can:
- Index the Bitcoin blockchain connecting to peers over Tor;
- Connect to a remote Bitcoin RPC reachable over Tor; and
- Broadcast transactions over Tor.
The qube `bitcoin` can:
- Create wallet addresses; and
- Sign transactions.
### Custom daemon parameters
You can set extra parameters for the daemon in
`~/.bitcoin/conf.d/bitcoin.conf.local`, this file will never be changed
externally.
One of these parameters is `prune`, which reduces storage requirements by
deleting old blocks. The downside is that it can't serve old blocks, can't be
used to rescan old wallet and is incompatible to serve any Electrum Server.
You can enable pruning in `/home/user/.bitcoin/conf.d/bitcoin.conf.local` by
specifying how many `MiB` of block files to retain:
```cfg
prune=550
```
### Bitcoin Core GUI
Do not use the GUI in the `sys-bitcoin` qube to edit configuration, it won't
persist and `bitcoin-qt` cannot be run at the same time as `bitcoind`.
You can use the GUI in the `bitcoin` qube, specially useful for an easy-to-use
interface for the Bitcoin Core Wallet.
### Connect to a remote Bitcoin RPC
#### Evaluation of remote Bitcoin RPC
You may wish to connect to a remote Bitcoin node with RPC available to:
- Lower disk space usage and to lower resource consumption by not having
multiple Bitcoin blockchains;
- Avoid changing scripts and configurations that expect the connection to be
working on `127.0.0.1:8332`, such as the Qrexec policy for connecting
Bitcoind RPC to the Electrum Servers.
But there are huge disadvantages to this method:
- [Bitcoin Core RPC does not have transport encryption](https://github.com/bitcoin/bitcoin/blob/master/doc/release-notes/release-notes-0.12.0.md#rpc-ssl-support-dropped).
Therefore, this method is advised against unless you know how to enable
transport encryption to connect to your Bitcoin RPC. If you run bitcoind on
`sys-bitcoin`, you do not have to worry about transport encryption as
communication is done securely via Qrexec.
- Bitcoin configuration cannot be changed remotely, therefore adding RPC
Authentication for clients such as Electrum Servers have to be done
manually.
The remote bitcoind setup is difficult to fit all user needs and requires you
to change a remote node we have no control over the configuration, therefore,
it is intended for advanced users only.
#### Configure the remote node
On the remote node:
- You must set in the node's `bitcoin.conf`, the following options to bind to
the external interface: `rpcbind`, `bind` (Electrs),
`whitelist=download@<ADDR>` (ElectRS), `zmqpubhashblock` (Fulcrum) and allow
connections of the external IP of your upstream netvm via `rpcallowip`.
- Open the configured ports of the previous settings in the firewall to be
reachable by the Qubes system.
- Generate RPC credentials (see `bitcoin/share/rpcauth/rpcauth.py`), add
`rpcauth=` option to `bitcoin.conf` and save the `user` and `password` for
later.
- Restart bitcoind to apply the configuration changes.
#### Connect the qube to the remote node
**Warning**: use of `sys-bitcoin` for the remote node connection is
discouraged as you either need to expose the node RPC port to an onion service
(preferably with Onion Authentication) or punch a hole in the Whonix firewall
so it can reach your LAN.
The following example uses the qube `sys-net` as a netvm that can connect
to your remote node running on the address `192.168.2.10`, RPC port `8332`,
P2P port `8333`, ZMQPUBHASHBLOCK port `8433`.
In `dom0`, create the user Qrexec policy to target the qube `sys-net` in
`/etc/qubes/policy.d/30-user.policy`:
```qrexecpolicy
## Getting Auth doesn't work with remote node.
qusal.BitcoinAuthGet * @anyvm @anyvm deny
qubes.ConnectTCP +8332 @tag:bitcoin-client @default allow target=sys-net
qubes.ConnectTCP +8333 @tag:bitcoin-client @default allow target=sys-net
qubes.ConnectTCP +8433 @tag:bitcoin-client @default allow target=sys-net
qubes.ConnectTCP * @tag:bitcoin-client @anyvm deny
```
In the qube `sys-net`, add the `socat` command (only the ones you need) to the
file `/rw/config/rc.local`:
```sh
## RPC
socat TCP-LISTEN:8332,reuseaddr,fork,bind=127.0.0.1 TCP:192.168.2.10:8332 &
## P2P (ElectRS)
socat TCP-LISTEN:8333,reuseaddr,fork,bind=127.0.0.1 TCP:192.168.2.10:8333 &
## ZMQPubHashBlock (Fulcrum)
socat TCP-LISTEN:8433,reuseaddr,fork,bind=127.0.0.1 TCP:192.168.2.10:8433 &
```
In the Electrum Server qubes or any Bitcoin Client, `sys-electrumx`,
`sys-electrs`, `sys-fulcrum`, add the `qvm-connect-tcp` command to the file
`/rw/config/rc.local`:
```sh
## RPC
qvm-connnect-tcp ::8332
## P2P (ElectRS)
qvm-connnect-tcp ::8333
## ZMQPubHashBlock (Fulcrum)
qvm-connnect-tcp ::8433
```
Still in the Electrum Server qube, you will have to add the RPC authentication
you got from the remote node to `~/.bitcoin/.cookie`.
Restart the qubes you modified the configuration to check if the service is
starting automatically on boot.
### Database on external drive
Your machine might not have enough disk space to store the database and you
don't want to configure a remote client. Unfortunately, this method is
unsupported. It may be possible, but as mounting the drive requires user
intervention, you are on your own to adjust the database path.
If you have done this, please share a guide.
## Credits
- [qubenix](https://github.com/qubenix/qubes-whonix-bitcoin)

View File

@ -0,0 +1,8 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
{% from 'utils/macros/sync-appmenus.sls' import sync_appmenus -%}
{{ sync_appmenus('bitcoin') }}

View File

@ -0,0 +1,10 @@
{#
SPDX-FileCopyrightText: 2023 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
base:
'dom0':
- match: nodegroup
- sys-bitcoin.appmenus

View File

@ -0,0 +1,8 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
{% from 'utils/macros/clone-template.sls' import clone_template -%}
{{ clone_template('whonix-workstation', sls_path) }}

View File

@ -0,0 +1,10 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
base:
'dom0':
- match: nodegroup
- sys-bitcoin.clone

View File

@ -0,0 +1,51 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
{% if grains['nodename'] != 'dom0' -%}
include:
- dev.home-cleanup
- dotfiles.copy-x11
- dotfiles.copy-sh
"{{ slsdotpath }}-gnupg-home":
file.directory:
- name: /home/user/.gnupg/bitcoin
- user: user
- group: user
- mode: '0700'
- makedirs: True
"{{ slsdotpath }}-save-keys":
file.recurse:
- require:
- file: "{{ slsdotpath }}-gnupg-home"
- name: /home/user/.gnupg/bitcoin/download/
- source: salt://{{ slsdotpath }}/files/server/keys/
- user: user
- group: user
- file_mode: '0600'
- dir_mode: '0700'
- makedirs: True
"{{ slsdotpath }}-import-keys":
cmd.run:
- require:
- file: "{{ slsdotpath }}-save-keys"
- name: gpg --status-fd=2 --homedir . --import download/*.asc
- cwd: /home/user/.gnupg/bitcoin
- runas: user
- success_stderr: IMPORT_OK
"{{ slsdotpath }}-import-ownertrust":
cmd.run:
- require:
- cmd: "{{ slsdotpath }}-import-keys"
- name: gpg --homedir . --import-ownertrust download/otrust.txt
- cwd: /home/user/.gnupg/bitcoin
- runas: user
{% endif -%}

View File

@ -0,0 +1,9 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
base:
'disp-bitcoin-builder':
- sys-bitcoin.configure-builder-common

View File

@ -0,0 +1,177 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
{% if grains['nodename'] != 'dom0' -%}
{% set bitcoin_tag = 'v26.0' -%}
include:
- .configure-builder-common
"{{ slsdotpath }}-source-makedir-src":
file.directory:
- name: /home/user/src
- user: user
- group: user
- mode: '0755'
- makedirs: True
"{{ slsdotpath }}-source-git-clone":
git.latest:
- name: https://github.com/bitcoin/bitcoin
- target: /home/user/src/bitcoin
- depth: 1
- rev: {{ bitcoin_tag }}
- user: user
- force_fetch: True
"{{ slsdotpath }}-source-git-verify-tag-{{ bitcoin_tag }}":
cmd.run:
- require:
- git: "{{ slsdotpath }}-source-git-clone"
- cmd: "{{ slsdotpath }}-import-ownertrust"
- env:
- GNUPGHOME: "/home/user/.gnupg/bitcoin"
- name: git -c gpg.program=gpg2 verify-tag "{{ bitcoin_tag }}"
- cwd: /home/user/src/bitcoin
- runas: user
"{{ slsdotpath }}-source-git-checkout-tag-{{ bitcoin_tag }}":
cmd.run:
- name: git checkout {{ bitcoin_tag }}
- require:
- cmd: "{{ slsdotpath }}-source-git-verify-tag-{{ bitcoin_tag }}"
- cwd: /home/user/src/bitcoin
- runas: user
"{{ slsdotpath }}-source-build-autogen":
cmd.run:
- require:
- cmd: "{{ slsdotpath }}-source-git-checkout-tag-{{ bitcoin_tag }}"
- name: ./autogen.sh
- cwd: /home/user/src/bitcoin
- runas: user
"{{ slsdotpath }}-source-build-configure":
cmd.run:
- require:
- cmd: "{{ slsdotpath }}-source-build-autogen"
- env:
- CXX: "clang++"
- CC: "clang"
- name: |
./configure \
--prefix=/home/user/bitcoin-build \
--disable-maintainer-mode \
--disable-tests \
--disable-bench \
--disable-fuzz-binary \
--disable-shared \
--disable-dependency-tracking \
--without-miniupnpc \
--without-natpmp \
--without-bdb \
--without-libs
- cwd: /home/user/src/bitcoin
- runas: user
"{{ slsdotpath }}-source-build-make-clean":
cmd.run:
- require:
- cmd: "{{ slsdotpath }}-source-build-configure"
- name: make clean
- cwd: /home/user/src/bitcoin
- runas: user
"{{ slsdotpath }}-source-build-make":
cmd.run:
- require:
- cmd: "{{ slsdotpath }}-source-build-make-clean"
- name: make -j "$(($(nproc)+1))"
- cwd: /home/user/src/bitcoin
- runas: user
"{{ slsdotpath }}-source-build-gen-manpages":
cmd.run:
- require:
- cmd: "{{ slsdotpath }}-source-build-make"
- name: ./contrib/devtools/gen-manpages.py
- cwd: /home/user/src/bitcoin
- runas: user
"{{ slsdotpath }}-source-build-gen-bitcoin-conf":
cmd.run:
- require:
- cmd: "{{ slsdotpath }}-source-build-make"
- name: ./contrib/devtools/gen-bitcoin-conf.sh
- cwd: /home/user/src/bitcoin
- runas: user
"{{ slsdotpath }}-source-build-make-install":
cmd.run:
- require:
- cmd: "{{ slsdotpath }}-source-build-make"
- name: make install
- cwd: /home/user/src/bitcoin
- runas: user
"{{ slsdotpath }}-source-readme":
cmd.run:
- require:
- cmd: "{{ slsdotpath }}-source-build-make-install"
- name: |
\mkdir -p share/bitcoin
\cp -v ~/src/bitcoin/README.md share/bitcoin/
- cwd: /home/user/bitcoin-build
- runas: user
"{{ slsdotpath }}-source-share-examples":
cmd.run:
- require:
- cmd: "{{ slsdotpath }}-source-build-make-install"
- name: |
\cp -v ~/src/bitcoin/share/examples/bitcoin.conf bitcoin.conf
- cwd: /home/user/bitcoin-build
- runas: user
"{{ slsdotpath }}-source-shell-completion":
cmd.run:
- require:
- cmd: "{{ slsdotpath }}-source-build-make-install"
- name: |
\mkdir -p share/bash-completion/completions/
\cp -v ~/src/bitcoin/contrib/completions/bash/* share/bash-completion/completions/
- cwd: /home/user/bitcoin-build
- runas: user
"{{ slsdotpath }}-source-rpcauth":
cmd.run:
- require:
- cmd: "{{ slsdotpath }}-source-build-make-install"
- name: |
\mkdir -p share/rpcauth
\cp -v ~/src/bitcoin/share/rpcauth/rpcauth.py share/rpcauth/
- cwd: /home/user/bitcoin-build
- runas: user
"{{ slsdotpath }}-source-rpcauth":
cmd.run:
- require:
- cmd: "{{ slsdotpath }}-source-build-make-install"
- name: |
\mkdir -p share/icons/hicolor/scalable/apps/
\cp -v ~/src/bitcoin/src/qt/res/src/bitcoin.svg share/icons/hicolor/scalable/apps/
- cwd: /home/user/bitcoin-build
- runas: user
"{{ slsdotpath }}-source-copy-files-to-template":
cmd.run:
- require:
- cmd: "{{ slsdotpath }}-source-build-make"
- name: qrexec-client-vm -T -- @default qusal.InstallBitcoin /usr/lib/qubes/qfile-agent /home/user/bitcoin-build/*
- runas: user
{% endif -%}

View File

@ -0,0 +1,9 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
base:
'disp-bitcoin-builder':
- sys-bitcoin.configure-builder-source

View File

@ -0,0 +1,98 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
{% if grains['nodename'] != 'dom0' -%}
## https://bitcoincore.org/bin/bitcoin-core-VERSION/
## bitcoin-26.0-x86_64-linux-gnu.tar.gz|SHA256SUMS|SHA256SUMS.asc
{% set bitcoin_version = '26.0' -%}
{% set bitcoin_url_dir = 'https://bitcoincore.org/bin/bitcoin-core-' ~ bitcoin_version ~ '/' -%}
{% set bitcoin_archive_dir = 'bitcoin-' ~ bitcoin_version -%}
{% set bitcoin_file_archive = bitcoin_archive_dir ~ '-x86_64-linux-gnu.tar.gz' -%}
{% set bitcoin_file_shasum = 'SHA256SUMS' -%}
{% set bitcoin_file_shasum_sig = bitcoin_file_shasum ~ '.asc' -%}
{% set bitcoin_url_archive = bitcoin_url_dir ~ bitcoin_file_archive -%}
{% set bitcoin_url_shasum = bitcoin_url_dir ~ bitcoin_file_shasum -%}
{% set bitcoin_url_shasum_sig = bitcoin_url_dir ~ bitcoin_file_shasum_sig -%}
include:
- .configure-builder-common
"{{ slsdotpath }}-remove-failed-download-or-verification":
file.absent:
- name: /tmp/bitcoin-download
- onfail:
- cmd: "{{ slsdotpath }}-download"
- cmd: "{{ slsdotpath }}-gpg-verify-shasum"
- cmd: "{{ slsdotpath }}-shasum-check"
"{{ slsdotpath }}-make-download-dir":
file.directory:
- name: /tmp/bitcoin-download
- mode: '0755'
- user: user
- group: user
- makedirs: True
## file.managed does not fetch URLs through a SocksProxy.
"{{ slsdotpath }}-download":
cmd.run:
- require:
- file: "{{ slsdotpath }}-make-download-dir"
- name: |
timeout --foreground 1200 curl.anondist-orig \
--connect-timeout 60 \
--tlsv1.3 --proto =https \
--fail --fail-early \
--proxy "socks5h://10.152.152.10:9400" \
--parallel --parallel-immediate \
--no-progress-meter --silent --show-error \
-O "{{ bitcoin_url_archive }}" \
-O "{{ bitcoin_url_shasum }}" \
-O "{{ bitcoin_url_shasum_sig }}"
- cwd: /tmp/bitcoin-download
- runas: user
"{{ slsdotpath }}-gpg-verify-shasum":
cmd.run:
- require:
- cmd: "{{ slsdotpath }}-download"
- cmd: "{{ slsdotpath }}-import-ownertrust"
## Multiple detached signatures has bad UX with GPG.
- name: |
trusted_sigs_number="4"
read_sigs_number="$(GNUPGHOME=/home/user/.gnupg/bitcoin/ gpg --status-fd=2 --verify SHA256SUMS.asc 2>&1 | grep -c "^\[GNUPG:\] GOODSIG \S\+ ")"
if test "${trusted_sigs_number}" != "${read_sigs_number}"; then
exit 1
fi
- cwd: /tmp/bitcoin-download
- runas: user
"{{ slsdotpath }}-shasum-check":
cmd.run:
- require:
- cmd: "{{ slsdotpath }}-gpg-verify-shasum"
- name: sha256sum --check --ignore-missing {{ bitcoin_file_shasum }}
- cwd: /tmp/bitcoin-download
- runas: user
"{{ slsdotpath }}-extract-archive":
archive.extracted:
- require:
- cmd: "{{ slsdotpath }}-shasum-check"
- name: /tmp/
- source: /tmp/bitcoin-download/{{ bitcoin_file_archive }}
- overwrite: True
- clean: True
"{{ slsdotpath }}-copy-files-to-template":
cmd.run:
- require:
- archive: "{{ slsdotpath }}-extract-archive"
- name: qrexec-client-vm -T -- @default qusal.InstallBitcoin /usr/lib/qubes/qfile-agent /tmp/{{ bitcoin_archive_dir }}/*
- runas: user
{% endif -%}

View File

@ -0,0 +1,9 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
base:
'disp-bitcoin-builder':
- sys-bitcoin.configure-builder

View File

@ -0,0 +1,60 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
{% if grains['nodename'] != 'dom0' -%}
include:
- dev.home-cleanup
- dotfiles.copy-x11
- dotfiles.copy-sh
- whonix-workstation.configure-offline
"{{ slsdotpath }}-client-desktop-applications":
file.recurse:
- name: /home/user/.local/share/applications/
- source: salt://{{ slsdotpath }}/files/client/applications/
- dir_mode: '0755'
- file_mode: '0644'
- user: user
- group: user
- makedirs: True
"{{ slsdotpath }}-client-autostart-desktop-applications":
file.symlink:
- name: /home/user/.config/autostart/bitcoin-qt.desktop
- target: /home/user/.local/share/applications/bitcoin-qt.desktop
- user: user
- group: user
- force: True
- makedirs: True
"{{ slsdotpath }}-client-bitcoin-configuration":
file.recurse:
- name: /home/user/.bitcoin/
- source: salt://{{ slsdotpath }}/files/client/conf/
- file_mode: '0600'
- dir_mode: '0700'
- user: user
- group: user
- makedirs: True
"{{ slsdotpath }}-client-bitcoin-touch-local-configuration":
file.managed:
- name: /home/user/.bitcoin/conf.d/bitcoin.conf.local
- mode: '0600'
- user: user
- group: user
- makedirs: True
"{{ slsdotpath }}-client-bitcoin-makedir-wallets":
file.directory:
- name: /home/user/.bitcoin/wallets
- mode: '0700'
- user: user
- group: user
- makedirs: True
{% endif -%}

View File

@ -0,0 +1,9 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
base:
'bitcoin':
- sys-bitcoin.configure-client

View File

@ -0,0 +1,21 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
{% if grains['nodename'] != 'dom0' -%}
"{{ slsdotpath }}-onion-grater-add-bitcoind":
cmd.run:
- name: onion-grater-add bitcoind
- runas: root
"{{ slsdotpath }}-systemd-restart-onion-grater":
service.running:
- name: onion-grater
- enable: True
- watch:
- cmd: "{{ slsdotpath }}-onion-grater-add-bitcoind"
{% endif -%}

View File

@ -0,0 +1,9 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
base:
'sys-bitcoin-gateway':
- sys-bitcoin.configure-gateway-listen

View File

@ -0,0 +1,57 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
{% if grains['nodename'] != 'dom0' -%}
include:
- dev.home-cleanup
- dotfiles.copy-sh
- dotfiles.copy-x11
"{{ slsdotpath }}-create-rc-script":
file.managed:
- name: /rw/config/rc.local.d/50-sys-bitcoin.rc
- source: salt://{{ slsdotpath }}/files/gateway/rc.local.d/50-sys-bitcoin.rc
- mode: '0755'
- user: root
- group: root
- makedirs: True
"{{ slsdotpath }}-torrc-bitcoin-socksport":
file.managed:
- name: /usr/local/etc/torrc.d/40_qusal.conf
- source: salt://{{ slsdotpath }}/files/gateway/torrc.d/40_qusal.conf
- template: jinja
- context:
qube_ip: {{ salt['cmd.shell']('qubesdb-read /qubes-ip') }}
- mode: '0644'
- user: root
- group: root
- makedirs: True
"{{ slsdotpath }}-systemd-restart-tor@default":
service.running:
- name: tor@default
- enable: True
- reload: True
- watch:
- file: "{{ slsdotpath }}-torrc-bitcoin-socksport"
"{{ slsdotpath }}-whonix-firewall-open-socksport":
file.managed:
- name: /usr/local/etc/whonix_firewall.d/40_qusal.conf
- source: salt://{{ slsdotpath }}/files/gateway/whonix_firewall.d/40_qusal.conf
- mode: '0644'
- user: root
- group: root
- makedirs: True
"{{ slsdotpath }}-whonix-firewall-reload":
cmd.run:
- name: whonix_firewall --info
- runas: root
{% endif -%}

View File

@ -0,0 +1,9 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
base:
'sys-bitcoin-gateway':
- sys-bitcoin.configure-gateway

View File

@ -0,0 +1,32 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
{% if grains['nodename'] != 'dom0' -%}
"{{ slsdotpath }}-bitcoind-listen-configuration":
file.managed:
- name: /home/user/.bitcoin/conf.d/listen.conf
- source: salt://{{ slsdotpath }}/files/server/conf-optional/listen.conf
- mode: '0600'
- user: user
- group: user
- makedirs: True
"{{ slsdotpath }}-whonix-firewall-open-bitcoin-listening":
file.managed:
- name: /usr/local/etc/whonix_firewall.d/40_qusal.conf
- source: salt://{{ slsdotpath }}/files/server/whonix_firewall.d/40_qusal.conf
- mode: '0600'
- user: root
- group: root
- makedirs: True
"{{ slsdotpath }}-whonix-firewall-reload":
cmd.run:
- name: whonix_firewall --info
- runas: root
{% endif -%}

View File

@ -0,0 +1,9 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
base:
'sys-bitcoin':
- sys-bitcoin.configure-listen

View File

@ -0,0 +1,48 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
{% if grains['nodename'] != 'dom0' -%}
include:
- dev.home-cleanup
- dotfiles.copy-x11
- dotfiles.copy-sh
"{{ slsdotpath }}-bitcoind-configuration":
file.recurse:
- name: /home/user/.bitcoin/
- source: salt://{{ slsdotpath }}/files/server/conf/
- file_mode: '0600'
- dir_mode: '0700'
- user: user
- group: user
- makedirs: True
"{{ slsdotpath }}-bitcoind-touch-local-configuration":
file.managed:
- name: /home/user/.bitcoin/conf.d/bitcoin.conf.local
- mode: '0600'
- user: user
- group: user
- makedirs: True
"{{ slsdotpath }}-bitcoind-touch-rpcauth-configuration":
file.managed:
- name: /home/user/.bitcoin/conf.d/rpcauth.conf
- mode: '0600'
- user: user
- group: user
- makedirs: True
"{{ slsdotpath }}-bitcoind-touch-listen-configuration":
file.managed:
- name: /home/user/.bitcoin/conf.d/listen.conf
- mode: '0600'
- user: user
- group: user
- makedirs: True
{% endif -%}

209
salt/sys-bitcoin/create.sls Normal file
View File

@ -0,0 +1,209 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
{%- from "qvm/template.jinja" import load -%}
{%- import "whonix-gateway/template.jinja" as whonix_gateway %}
include:
- .clone
{% load_yaml as defaults -%}
name: {{ slsdotpath }}-gateway
force: True
require:
- sls: {{ slsdotpath }}.clone
present:
- template: {{ whonix_gateway.template }}
- label: orange
prefs:
- template: {{ whonix_gateway.template }}
- label: orange
- audiovm: ""
- default_dispvm: ""
- vcpus: 1
- memory: 300
- maxmem: 500
- provides-network: True
- include_in_backups: True
- autostart: False
features:
- enable:
- servicevm
- disable:
- service.cups
- service.cups-browsed
tags:
- add:
- "anon-bitcoin-gateway"
- del:
- "anon-gateway"
{%- endload %}
{{ load(defaults) }}
{% load_yaml as defaults -%}
name: tpl-{{ slsdotpath }}
force: True
require:
- sls: {{ slsdotpath }}.clone
prefs:
- audiovm: ""
- default_dispvm: ""
tags:
- add:
- "updatevm-sys-bitcoin-gateway"
- del:
- "whonix-updatevm"
{%- endload %}
{{ load(defaults) }}
{% load_yaml as defaults -%}
name: {{ slsdotpath }}
force: True
require:
- sls: {{ slsdotpath }}.clone
present:
- template: tpl-{{ slsdotpath }}
- label: yellow
prefs:
- template: tpl-{{ slsdotpath }}
- label: yellow
- netvm: {{ slsdotpath }}-gateway
- audiovm: ""
- default_dispvm: ""
- vcpus: 4
- memory: 400
- maxmem: 2500
- autostart: False
- include_in_backups: True
features:
- enable:
- servicevm
- service.bitcoin-server
- disable:
- service.cups
- service.cups-browsed
- service.meminfo-writer
tags:
- add:
- "anon-bitcoin-vm"
- del:
- "anon-vm"
{%- endload %}
{{ load(defaults) }}
{% load_yaml as defaults -%}
name: dvm-bitcoin-builder
force: True
require:
- qvm: tpl-{{ slsdotpath }}
present:
- template: tpl-{{ slsdotpath }}
- label: red
prefs:
- template: tpl-{{ slsdotpath }}
- label: red
- netvm: {{ slsdotpath }}-gateway
- audiovm: ""
- default_dispvm: ""
- vcpus: 4
- memory: 400
- maxmem: 2000
- autostart: False
- template_for_dispvms: True
features:
- disable:
- service.cups
- service.cups-browsed
tags:
- add:
- "anon-bitcoin-vm"
- del:
- "anon-vm"
{%- endload %}
{{ load(defaults) }}
{% load_yaml as defaults -%}
name: disp-bitcoin-builder
force: True
require:
- qvm: dvm-bitcoin-builder
present:
- template: dvm-bitcoin-builder
- label: red
- class: DispVM
prefs:
- template: dvm-bitcoin-builder
- label: red
- netvm: {{ slsdotpath }}-gateway
- audiovm: ""
- vcpus: 4
- memory: 400
- maxmem: 2000
- autostart: False
- include_in_backups: False
features:
- disable:
- appmenus-dispvm
- service.cups
- service.cups-browsed
tags:
- add:
- "anon-bitcoin-vm"
- del:
- "anon-vm"
{%- endload %}
{{ load(defaults) }}
{% load_yaml as defaults -%}
name: bitcoin
force: True
require:
- sls: {{ slsdotpath }}.clone
present:
- template: tpl-{{ slsdotpath }}
- label: gray
prefs:
- template: tpl-{{ slsdotpath }}
- label: gray
- netvm: ""
- audiovm: ""
- default_dispvm: ""
- vcpus: 4
- memory: 400
- maxmem: 600
- autostart: False
- include_in_backups: True
features:
- disable:
- service.cups
- service.cups-browsed
- set:
- menu-items: "bitcoin-qt.desktop qubes-open-file-manager.desktop qubes-run-terminal.desktop qubes-start.desktop"
tags:
- del:
- "bitcoin-client"
{%- endload %}
{{ load(defaults) }}
## TODO: remove comment of volume extension
{#
"{{ slsdotpath }}-extend-private-volume":
cmd.run:
- require:
- qvm: {{ slsdotpath }}
- name: qvm-volume extend {{ slsdotpath }}:private 1Ti
#}
"{{ slsdotpath }}-extend-builder-private-volume":
cmd.run:
- require:
- qvm: disp-bitcoin-builder
- name: qvm-volume extend dvm-bitcoin-builder:private 20Gi
{% from 'utils/macros/policy.sls' import policy_set with context -%}
{{ policy_set(sls_path, '70') }}

View File

@ -0,0 +1,10 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
base:
'dom0':
- match: nodegroup
- sys-bitcoin.create

View File

@ -0,0 +1,32 @@
# SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
## Do not modify this file, create a new policy with with a lower number in the
## file name instead. For example `30-user.policy`.
qusal.InstallBitcoin * disp-bitcoin-builder @default allow target=tpl-sys-bitcoin user=root autostart=yes
qusal.InstallBitcoin * @anyvm @anyvm deny
qusal.BitcoinAuthGet * @tag:bitcoin-client @default allow target=sys-bitcoin user=root
qusal.BitcoinAuthGet * @anyvm @anyvm deny
qubes.ConnectTCP +8332 @tag:bitcoin-client @default allow target=sys-bitcoin
qubes.ConnectTCP +8333 @tag:bitcoin-client @default allow target=sys-bitcoin
qubes.ConnectTCP +8433 @tag:bitcoin-client @default allow target=sys-bitcoin
qubes.ConnectTCP * @tag:bitcoin-clinet @anyvm deny
qubes.UpdatesProxy * @tag:updatevm-sys-bitcoin-gateway @default allow target=sys-bitcoin-gateway
qubes.UpdatesProxy * @tag:updatevm-sys-bitcoin-gateway @anyvm deny
whonix.NewStatus * @tag:anon-bitcoin-vm @anyvm allow target=sys-bitcoin-gateway autostart=no
whonix.NewStatus * @tag:anon-bitcoin-vm @anyvm deny
whonix.SdwdateStatus + sys-bitcoin-gateway @tag:anon-bitcoin-vm allow autostart=no notify=no
whonix.SdwdateStatus + sys-bitcoin-gateway @default deny
whonix.SdwdateStatus * sys-bitcoin-gateway @anyvm deny
whonix.GatewayCommand +restart sys-bitcoin-gateway @tag:anon-bitcoin-vm allow autostart=no
whonix.GatewayCommand +stop sys-bitcoin-gateway @tag:anon-bitcoin-vm allow autostart=no
whonix.GatewayCommand +showlog sys-bitcoin-gateway @tag:anon-bitcoin-vm allow autostart=no
whonix.GatewayCommand * sys-bitcoin-gateway @anyvm deny
## vim:ft=qrexecpolicy

View File

@ -0,0 +1,16 @@
## SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
##
## SPDX-License-Identifier: AGPL-3.0-or-later
[Desktop Entry]
Name=Bitcoin Core
Comment=Connect to the Bitcoin P2P Network
Exec=bitcoin-qt %u
Terminal=false
Hidden=false
Type=Application
## Icon only appears if core was built from source.
Icon=bitcoin
MimeType=x-scheme-handler/bitcoin;
Categories=Finance;P2P;Network;Qt;
StartupWMClass=Bitcoin-QT

View File

@ -0,0 +1,19 @@
#!/bin/sh
## SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
##
## SPDX-License-Identifier: AGPL-3.0-or-later
set -eu
if test -s ~/.bitcoin/.cookie; then
exit 0
fi
auth="$(qrexec-client-vm -tT -- @default qusal.BitcoinAuthGet)"
if test -n "${auth}"; then
mkdir -p ~/.bitcoin/.cookie
echo "${auth}" | tee ~/.bitcoin/.cookie >/dev/null
else
echo "failed to get Bitcoin Authentication" >&2
exit 1
fi

View File

@ -0,0 +1,24 @@
#!/bin/sh
## SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
##
## SPDX-License-Identifier: AGPL-3.0-or-later
set -eu
qube="$(qubesdb-read /name)"
txid="${1}"
wallet="${2}"
block_hash="${3}"
block_height="${4-}"
title="${qube}: wallet: ${wallet}"
date="$(date +%FT%H:%m:%SZ)"
if test "${block_hash}" = "unconfirmed"; then
body="TXID ${txid} is ${block_hash}"
else
body="TXID ${txid} is in block ${block_height} ${block_hash}"
fi
echo "${date} ${title}: ${body}" | tee ~/.bitcoin/walletnotify.log
if command -v notify-send >/dev/null; then
notify-send -t 10000 "${title}" "${body}"
fi

View File

@ -0,0 +1,32 @@
## SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
##
## SPDX-License-Identifier: AGPL-3.0-or-later
## Main
datadir=/home/user/.bitcoin
server=1
daemon=0
## Offline
listen=0
listenonion=0
networkactive=0
walletbroadcast=0
## $HOME has only 2GB which leads to warnings unless user has to manually
## modify GUI settings as the GUI ignores the 'prune=' option from the
## configuration file, at least for the warning. /tmp has enough space.
blocksdir=/tmp
prune=550
## Avoid space and corruption warnings as we can't fetch blocks and the blocks
## directory is discarded.
reindex=1
## Wallet
disablewallet=0
walletnotify=bitcoin-tx-notify %s %w %b %h
## External configuration
includeconf=conf.d/bitcoin.conf.local
# vim: ft=config

View File

@ -0,0 +1,14 @@
## SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
##
## SPDX-License-Identifier: AGPL-3.0-or-later
[Unit]
Description=Bitcoin RPC over Qrexec
PartOf=bitcoin-rpc-qrexec.service
[Socket]
ListenStream=127.0.0.1:8332
Accept=true
[Install]
WantedBy=sockets.target

View File

@ -0,0 +1,16 @@
## SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
##
## SPDX-License-Identifier: AGPL-3.0-or-later
[Unit]
Description=Bitcoin RPC over Qrexec
ConditionPathExists=/var/run/qubes-service/bitcoin-client
Requires=bitcoin-rpc-qrexec.socket
After=qubes-sysinit.service
After=qubes-qrexec-agent.service
After=bitcoin-rpc-qrexec.socket
[Service]
ExecStart=qrexec-client-vm @default qubes.ConnectTCP+8332
StandardInput=socket
StandardOutput=inherit

View File

@ -0,0 +1,8 @@
#!/bin/sh
## SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
##
## SPDX-License-Identifier: AGPL-3.0-or-later
update-alternatives --set x-terminal-emulator /usr/bin/xterm
# vim: ft=sh

View File

@ -0,0 +1,9 @@
## SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
##
## SPDX-License-Identifier: AGPL-3.0-or-later
SocksPort 127.0.0.1:9400 IsolateDestAddr IsolateDestPort
SocksPort 127.0.0.1:9401 IsolateDestAddr IsolateDestPort OnionTrafficOnly
SocksPort {{ qube_ip }}:9400 IsolateDestAddr IsolateDestPort
SocksPort {{ qube_ip }}:9401 IsolateDestAddr IsolateDestPort OnionTrafficOnly

View File

@ -0,0 +1,12 @@
## SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
##
## SPDX-License-Identifier: AGPL-3.0-or-later
## Opens distinct SocksPort for Bitcoin.
INTERNAL_OPEN_PORTS+=" 9400 9401 "
## Blocks Workstation access to tor's TransPort and DNSPort.
WORKSTATION_TRANSPARENT_TCP=0
WORKSTATION_TRANSPARENT_DNS=0
# vim: ft=bash

View File

@ -0,0 +1,11 @@
#!/bin/sh
## SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
##
## SPDX-License-Identifier: AGPL-3.0-or-later
set -eu
conf="${HOME}/.bitcoin/conf.d/dbcache.conf"
cache_Mi="$(awk '/^MemTotal:/{printf "%.0f", $2/1024}' /proc/meminfo)"
cache="$((cache_Mi*75/100))"
echo "dbcache=${cache}" | tee "${conf}" >/dev/null

View File

@ -0,0 +1,17 @@
#!/bin/sh
## SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
##
## SPDX-License-Identifier: AGPL-3.0-or-later
set -eu
conf="${HOME}/.bitcoin/conf.d/cookie.conf"
if ! systemctl is-active bitcoind >/dev/null 2>&1; then
echo "systemd service 'bitcoind' is not active, remote RPC cannot add crendtials" >&2
exit 1
fi
rpc_list="$(bitcoin-cli help | awk '/^[a-z]/{print $1}' | tr "\n" ",")"
echo "rpcwhitelist=__cookie__:${rpc_list}" | tee "${conf}" >/dev/null

View File

@ -0,0 +1,94 @@
#!/bin/bash
## SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
##
## SPDX-License-Identifier: AGPL-3.0-or-later
set -eu
#date_mined="20130604"
#block_number="230009"
block_hash="00000000000000ecbbff6bafb7efa2f7df05b227d5c73dca8f2635af32a2e949"
txid="54e48e5f5c656b26c3bca14a8c95aa583d07ebe84dde3b7dd4a78f4e4186e713"
dir="${HOME}"
file="bitcoin.pdf"
has(){
cmd="$(command -v "${1}" 2>/dev/null)" || return 1
test -x "${cmd}" || return 1
}
check_installed(){
missing_programs=0
for prog in "${@}"; do
if ! has "${prog}"; then
echo "Missing program: ${prog}" >&2
missing_programs=1
fi
done
if test "${missing_programs}"; then
exit 1
fi
}
validate_dir(){
if ! test -d "${dir}"; then
echo "Directory '${dir}' does not exist" >&2
exit 1
fi
if ! test -w "${dir}"; then
echo "Directory '${dir}' is not writable" >&2
exit 1
fi
}
getblock(){
check_installed bitcoin-cli xxd
bitcoin-cli getblock "${block_hash}" 0 \
| tail -c+92167 \
| for ((o=0;o<946;++o)); do read -rN420 x; echo -n "${x::130}${x:132:130}${x:264:130}" ; done \
| xxd -r -p \
| tail -c+9 \
| head -c184292 \
| tee "${output_file}" >/dev/null
}
getrawtransaction(){
check_installed bitcoin-cli xxd
bitcoin-cli getrawtransaction "${txid}" 0 "${block_hash}" \
| sed 's/0100000000000000/\n/g' \
| tail -n +2 \
| cut -c7-136,139-268,271-400 \
| tr -d '\n' \
| cut -c17-368600 \
| xxd -p -r \
| tee "${output_file}" >/dev/null
}
gettxout(){
check_installed bitcoin-cli jq xxd seq
seq 0 947 \
| (while read -r n; do bitcoin-cli gettxout "${txid}" "${n}" \
| jq -r '.scriptPubKey.asm' \
| awk '{ print $2 $3 $4 }'; done) \
| tr -d '\n' \
| cut -c 17-368600 \
| xxd -r -p \
| tee "${output_file}" >/dev/null
}
usage(){
echo "Usage: ${0##*/} getblock|getrawtransaction|gettxtout [DIR]"
echo "Note: gettxtout works with pruned node"
echo "Note: DIR defaults to \$HOME"
exit 1
}
case "${1:-}" in
"getblock"|"getrawtransaction"|"gettxtout")
test -z "${2}" || dir="${2}"
validate_dir "${dir}"
output_file="${dir}/${file}"
"${1}"
;;
*) usage;;
esac

View File

@ -0,0 +1,11 @@
## SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
##
## SPDX-License-Identifier: AGPL-3.0-or-later
## Listen
listen=1
listenonion=1
bind=0.0.0.0:8334=onion
maxuploadtarget=144
# vim: ft=config

View File

@ -0,0 +1,46 @@
## SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
##
## SPDX-License-Identifier: AGPL-3.0-or-later
## Main
datadir=/home/user/.bitcoin
bind=127.0.0.1
server=1
daemon=0
## CPU optimization
rpcthreads=200
## Security
disablewallet=1
## TODO: use 'debug=rpc' with sys-bitcoin clients and configure 'rpcwhitelist'
#rpcwhitelistdefault=1
## TODO: remove rpcwhitelistdefault=0, because cookie user rpcwhitelist is set.
rpcwhitelistdefault=0
## RPC
rpcbind=127.0.0.1
rpcallowip=127.0.0.1
rpcconnect=127.0.0.1
## Proxy
#listenonion=0
proxyrandomize=1
proxy=10.152.152.10:9400
onion=10.152.152.10:9401
## ElectRS
whitelist=download@127.0.0.1
## ElectrumX, Fulcrum and block explorers.
txindex=1
## Fulcrum
zmqpubhashblock=tcp://127.0.0.1:8433
## External configuration
includeconf=conf.d/rpcauth.conf
includeconf=conf.d/listen.conf
includeconf=conf.d/cookie.conf
includeconf=conf.d/dbcache.conf
includeconf=conf.d/bitcoin.conf.local
# vim: ft=config

View File

@ -0,0 +1,9 @@
## SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
##
## SPDX-License-Identifier: AGPL-3.0-or-later
## Bitcoind 'rpcwhitelistdefault=1' blocks the '__cookie__' user RPC calls.
## Whitelist generated on Bitcoin Core v26.0 using "bitcoin-rpcwhitelist-cookie"
# vim: ft=config
rpcwhitelist=__cookie__:dumptxoutset,getbestblockhash,getblock,getblockchaininfo,getblockcount,getblockfilter,getblockfrompeer,getblockhash,getblockheader,getblockstats,getchainstates,getchaintips,getchaintxstats,getdeploymentinfo,getdifficulty,getmempoolancestors,getmempooldescendants,getmempoolentry,getmempoolinfo,getrawmempool,gettxout,gettxoutproof,gettxoutsetinfo,gettxspendingprevout,importmempool,loadtxoutset,preciousblock,pruneblockchain,savemempool,scanblocks,scantxoutset,verifychain,verifytxoutproof,getmemoryinfo,getrpcinfo,help,logging,stop,uptime,getblocktemplate,getmininginfo,getnetworkhashps,getprioritisedtransactions,prioritisetransaction,submitblock,submitheader,addnode,clearbanned,disconnectnode,getaddednodeinfo,getaddrmaninfo,getconnectioncount,getnettotals,getnetworkinfo,getnodeaddresses,getpeerinfo,listbanned,ping,setban,setnetworkactive,analyzepsbt,combinepsbt,combinerawtransaction,converttopsbt,createpsbt,createrawtransaction,decodepsbt,decoderawtransaction,decodescript,descriptorprocesspsbt,finalizepsbt,getrawtransaction,joinpsbts,sendrawtransaction,signrawtransactionwithkey,submitpackage,testmempoolaccept,utxoupdatepsbt,enumeratesigners,createmultisig,deriveaddresses,estimatesmartfee,getdescriptorinfo,getindexinfo,signmessagewithprivkey,validateaddress,verifymessage,getzmqnotifications

View File

@ -0,0 +1,101 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
P7b4dgks4w/G21nheQNQ+F4xj4Tk8A==
=kTcq
-----END PGP PUBLIC KEY BLOCK-----

View File

@ -0,0 +1,109 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
pjc/06iI1r+A93XMRcY5IIps9SRInOpGT8f0
=tOut
-----END PGP PUBLIC KEY BLOCK-----

View File

@ -0,0 +1,64 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
wFpBigQ0wNJzl5R0779z4rP4KI0IQbwAJpc=
=Q4sq
-----END PGP PUBLIC KEY BLOCK-----

View File

@ -0,0 +1,122 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
=Suu+
-----END PGP PUBLIC KEY BLOCK-----

View File

@ -0,0 +1,77 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
=d2GD
-----END PGP PUBLIC KEY BLOCK-----

View File

@ -0,0 +1,106 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
=1fEC
-----END PGP PUBLIC KEY BLOCK-----

View File

@ -0,0 +1,52 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
gW0AV1VMe5a6JfA=
=eLyB
-----END PGP PUBLIC KEY BLOCK-----

View File

@ -0,0 +1,9 @@
# List of assigned trustvalues, created Thu 02 Nov 2023 09:43:48 PM UTC
# (Use "gpg --import-ownertrust" to restore them)
152812300785C96444D3334D17565732E08E5E41:6:
28F5900B1BB5D1A4B6B6D1A9ED357015286A333D:6:
4D1B3D5ECBA1A7E05371EEBE46800E30FC748A66:6:
6B002C6EA3F91B1B0DF0C9BC8F617F1200A6D25C:6:
9DEAE0DC7063249FB05474681E4AED62986CD25D:6:
CFB16E21C950F67FA95E558F2EEB9F5CC09526C1:6:
D1DBF2C4B96F2DEBF4C16654410108112E7EA81F:6:

View File

@ -0,0 +1,45 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# Creates a new rpcauth for the client qube if it does not exist. If bitcoind
# is running remotely, there is no way to set a new option with bitcoin-cli.
set -eu
bitcoin_conf="/home/user/.bitcoin/conf.d/rpcauth.conf"
bitcoin_pass="/home/user/.bitcoin/rpcclient.pass"
user="${QREXEC_REMOTE_DOMAIN}"
if ! systemctl is-active bitcoind >/dev/null 2>&1; then
echo "systemd service 'bitcoind' is not active, cannot add credentials with remote RPC" >&2
exit 1
fi
if test -r "${bitcoin_conf}"; then
if grep -qs "^\s*rpcauth=${user}:" "${bitcoin_conf}"; then
grep -m1 "^${user}:" "${bitcoin_pass}"
exit
fi
fi
if ! command -v bitcoin-rpcauth >/dev/null; then
echo "command not found: bitcoin-rpcauth" >&2
exit 127
fi
full_auth="$(bitcoin-rpcauth "${user}" | sed -n '2p;4p')"
rpcauth="$(echo "${full_auth}" | head -1)"
user="$(echo "${rpcauth}" | cut -d "=" -f2 | cut -d ":" -f1)"
password="$(echo "${full_auth}" | tail -1)"
echo "${rpcauth}" | sudo -u user tee -a "${bitcoin_conf}" >/dev/null
echo "${user}:${password}" | sudo -u user tee -a "${bitcoin_pass}" >/dev/null
echo "${user}:${password}"
## Restart bitcoind to apply the configuration changes. Currently, there is no
## prevention of DDoS besides when the client already has an authentication
## configured, it is printed and returned before getting to this part.
systemctl restart bitcoind

View File

@ -0,0 +1,31 @@
#!/bin/sh
## SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
##
## SPDX-License-Identifier: AGPL-3.0-or-later
set -eu
prefix_dir="/usr"
bin_dir="${prefix_dir}/bin"
share_dir="${prefix_dir}/share/bitcoin"
share_examples_dir="${share_dir}/examples"
tmp_dir="/tmp/bitcoin-upload"
rm -rf "${tmp_dir}"
mkdir -p "${tmp_dir}"
mkdir -p "${share_dir}"
mkdir -p "${share_examples_dir}"
qfile-unpacker 0 "${tmp_dir}"
cd "${tmp_dir}"
cp -r bin share "${prefix_dir}"/
if test -f README.md; then
cp -r README.md "${share_dir}"/
fi
if test -f bitcoin.conf; then
cp -r bitcoin.conf "${share_examples_dir}"/
fi
cp share/rpcauth/rpcauth.py "${bin_dir}"/bitcoin-rpcauth
## Qube needs to shutdown for the app qube to have the uploaded files.
shutdown now

View File

@ -0,0 +1,48 @@
## SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
##
## SPDX-License-Identifier: AGPL-3.0-or-later
[Unit]
Description=Bitcoin daemon
Documentation=https://github.com/bitcoin/bitcoin/blob/master/doc/init.md
ConditionPathExists=/var/run/qubes-service/bitcoin-server
ConditionPathExists=/usr/bin/bitcoind
ConditionPathExists=/usr/bin/bitcoin-cli
ConditionPathExists=/home/user/.bitcoin/bitcoin.conf
After=qubes-sysinit.service
After=network-online.target
Wants=network-online.target
[Service]
PermissionsStartOnly=true
Environment="MALLOC_ARENA_MAX=1"
ExecStartPre=/bin/chgrp user /home/user/.bitcoin
ExecStartPre=/usr/bin/bitcoin-dbcache
ExecStart=/usr/bin/bitcoind \
-daemon=0 \
-conf=/home/user/.bitcoin/bitcoin.conf \
-startupnotify='systemd-notify --ready' \
-shutdownnotify='systemd-notify --stopping'
ExecStop=/usr/bin/bitcoin-cli stop
Type=notify
NotifyAccess=all
PIDFile=/run/bitcoind/bitcoind.pid
Restart=on-failure
TimeoutStartSec=infinity
TimeoutStopSec=600
User=user
Group=user
RuntimeDirectory=bitcoind
RuntimeDirectoryMode=0710
ConfigurationDirectory=bitcoin
ConfigurationDirectoryMode=0710
StateDirectory=bitcoind
StateDirectoryMode=0710
PrivateTmp=true
ProtectSystem=full
NoNewPrivileges=true
PrivateDevices=true
MemoryDenyWriteExecute=true
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,6 @@
## SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
##
## SPDX-License-Identifier: AGPL-3.0-or-later
EXTERNAL_OPEN_PORTS+=" 8334 "
# vim: ft=bash

20
salt/sys-bitcoin/init.top Normal file
View File

@ -0,0 +1,20 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
base:
'dom0':
- match: nodegroup
- sys-bitcoin.create
'sys-bitcoin-gateway':
- sys-bitcoin.configure-gateway
'tpl-sys-bitcoin':
- sys-bitcoin.install
'disp-bitcoin-builder':
- sys-bitcoin.configure-builder
'sys-bitcoin':
- sys-bitcoin.configure
'bitcoin':
- sys-bitcoin.configure-client

View File

@ -0,0 +1,39 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
{% if grains['nodename'] != 'dom0' -%}
include:
- .install-common
- dev.home-cleanup
- dotfiles.copy-x11
- dotfiles.copy-sh
"{{ slsdotpath }}-client-bin":
file.recurse:
- name: /usr/bin/
- source: salt://{{ slsdotpath }}/files/client/bin/
- file_mode: '0755'
- dir_mode: '0755'
- user: root
- group: root
- makedirs: True
"{{ slsdotpath }}-client-systemd":
file.recurse:
- name: /usr/lib/systemd/system/
- source: salt://{{ slsdotpath }}/files/client/systemd/
- file_mode: '0644'
- dir_mode: '0755'
- user: root
- group: root
- makedirs: True
"{{ slsdotpath }}-client-system-service-enable-bitcoin-rpc-qrexec":
service.enabled:
- name: bitcoin-rpc-qrexec.socket
{% endif -%}

View File

@ -0,0 +1,9 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
base:
'*':
- sys-bitcoin.install-client

View File

@ -0,0 +1,88 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
{% if grains['nodename'] != 'dom0' -%}
include:
- dev.home-cleanup
- dev.install-terminal
- dotfiles.copy-x11
- dotfiles.copy-sh
- whonix-workstation.install-nostart-tbb
"{{ slsdotpath }}-common-updated":
pkg.uptodate:
- refresh: True
"{{ slsdotpath }}-common-installed":
pkg.installed:
- refresh: True
- install_recommends: False
- skip_suggestions: True
- pkgs:
- qubes-core-agent-networking
- ca-certificates
- man-db
- bash-completion
- jq
- socat
- curl
{% set pkg = {
'Debian': {
'pkg': ['libxcb1-dev', 'libxcb-icccm4', 'libxcb-image0-dev',
'libxcb-keysyms1-dev', 'libxcb-render0-dev',
'libxcb-render-util0-dev', 'libxcb-shape0-dev',
'libxcb-xinerama0-dev', 'libxcb-xkb-dev', 'libxcb-xinput0',
'libxkbcommon-x11-dev'],
},
'RedHat': {
'pkg': ['libxcb', 'xcb-util', 'xcb-util-wm', 'xcb-util-image',
'xcb-util-keysyms', 'libxkbcommon'],
},
}.get(grains.os_family) -%}
"{{ slsdotpath }}-common-installed-os-specific":
pkg.installed:
- refresh: True
- install_recommends: False
- skip_suggestions: True
- pkgs: {{ pkg.pkg|sequence|yaml }}
"{{ slsdotpath }}-bin":
file.recurse:
- name: /usr/bin/
- source: salt://{{ slsdotpath }}/files/server/bin/
- file_mode: '0755'
- dir_mode: '0755'
- user: user
- group: user
- makedirs: True
"{{ slsdotpath }}-rpc":
file.recurse:
- name: /etc/qubes-rpc/
- source: salt://{{ slsdotpath }}/files/server/rpc/
- dir_mode: '0755'
- file_mode: '0755'
- user: root
- group: root
- makedirs: True
"{{ slsdotpath }}-system-systemd-dir":
file.recurse:
- source: salt://{{ slsdotpath }}/files/server/systemd/
- name: /usr/lib/systemd/system/
- dir_mode: '0755'
- file_mode: '0644'
- user: root
- group: root
"{{ slsdotpath }}-system-service-enable-bitcoind":
service.enabled:
- name: bitcoind
{% endif -%}

View File

@ -0,0 +1,9 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
base:
'tpl-sys-bitcoin':
- sys-bitcoin.install-common

View File

@ -0,0 +1,61 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
{% if grains['nodename'] != 'dom0' -%}
include:
- .install-common
- dotfiles.copy-ssh
- dotfiles.copy-git
- sys-git.install-client
"{{ slsdotpath }}-source-installed":
pkg.installed:
- refresh: True
- install_recommends: False
- skip_suggestions: True
- pkgs:
- clang
- ccache
- help2man
{% set pkg = {
'Debian': {
'pkg': ['build-essential', 'libtool', 'autotools-dev', 'automake',
'pkg-config', 'bsdmainutils', 'python3', 'libevent-dev',
'libboost-dev', 'libsqlite3-dev', 'libzmq3-dev'],
},
'RedHat': {
'pkg': ['gcc-c++', 'libtool', 'make', 'autoconf', 'automake', 'python3',
'libevent-devel', 'boost-devel', 'sqlite-devel', 'zeromq-devel'],
},
}.get(grains.os_family) -%}
"{{ slsdotpath }}-source-installed-os-specific":
pkg.installed:
- refresh: True
- install_recommends: False
- skip_suggestions: True
- pkgs: {{ pkg.pkg|sequence|yaml }}
{% set pkg = {
'Debian': {
'pkg': ['libqt5gui5', 'libqt5core5a', 'libqt5dbus5', 'qttools5-dev',
'qttools5-dev-tools', 'libqrencode-dev'],
},
'RedHat': {
'pkg': ['qt5-qttools-devel', 'qt5-qtbase-devel', 'qrencode-devel'],
},
}.get(grains.os_family) -%}
"{{ slsdotpath }}-source-qt-installed-os-specific":
pkg.installed:
- refresh: True
- install_recommends: False
- skip_suggestions: True
- pkgs: {{ pkg.pkg|sequence|yaml }}
{% endif -%}

View File

@ -0,0 +1,10 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
base:
'tpl-sys-bitcoin':
- match: list
- sys-bitcoin.install-source

View File

@ -0,0 +1,12 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
{% if grains['nodename'] != 'dom0' -%}
include:
- .install-common
{% endif -%}

View File

@ -0,0 +1,10 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
base:
'tpl-sys-bitcoin':
- match: list
- sys-bitcoin.install

View File

@ -0,0 +1,59 @@
# sys-electrs
Electrs in Qubes OS.
## Table of Contents
* [Description](#description)
* [Installation](#installation)
* [Usage](#usage)
* [Credits](#credits)
## Description
Setup an offline Electrs (Electrum Server) qube named "sys-electrs",
connected to your own full node running on "sys-bitcoin" to index the
blockchain to allow for efficient query of the history of arbitrary addresses.
A disposable qube "disp-electrs-builder" will be created, based on
Whonix-Workstation, it will server to install and verify Electrs. After the
verification succeeds, files are copied to the template "tpl-sys-electrs".
This method was chosen so the server can be always offline.
At least `200GB` of disk space is required.
## Installation
This formula depends on [sys-bitcoin](../sys-bitcoin/README.md).
- Top
```sh
qubesctl top.enable sys-electrs
qubesctl --targets=tpl-electrs-builder,tpl-sys-electrs,disp-electrs-builder,sys-electrs state.apply
qubesctl top.disable sys-electrs
```
- State
<!-- pkg:begin:post-install -->
```sh
qubesctl state.apply sys-electrs.create
qubesctl --skip-dom0 --targets=tpl-electrs-builder state.apply sys-electrs.install-builder
qubesctl --skip-dom0 --targets=tpl-sys-electrs state.apply sys-electrs.install
qubesctl --skip-dom0 --targets=disp-electrs-builder state.apply sys-electrs.configure-builder
qubesctl --skip-dom0 --targets=sys-electrs state.apply sys-electrs.configure
```
<!-- pkg:end:post-install -->
## Usage
You may customize Electrs by writing to the file
`~/.electrs/conf.d/electrs.conf.local`.
If you are not using [sys-bitcoin](../sys-bitcoin/README.md), you will need to
add the RPC Authentication cookie to the qube `sys-electrs` in the file
`~/.bitcoin/.cookie`. Make sure there is no new line at the end of the cookie
file, else Electrs will fail to start.
## Credits
- [qubenix](https://github.com/qubenix/qubes-whonix-bitcoin)

View File

@ -0,0 +1,39 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
{% from 'utils/macros/clone-template.sls' import clone_template -%}
{{ clone_template('debian-minimal', sls_path) }}
{{ clone_template('debian-minimal', 'electrs-builder', include_create=False) }}
{#
TODO: Recheck: Cargo index fetch isis too big to be fetched over tor.
Impossible to fetch Cargo index over tor as of Bookworm Cargo 1.65.
Cargo >=1.68 does support "sparse" registry protocol,
https://blog.rust-lang.org/inside-rust/2023/01/30/cargo-sparse-protocol.html
This would partially solve the issue, shallow clone is still an open issue.
Command "cargo --config http.proxy=\"socks5h://10.152.152.10:9400\" build --locked --release --no-default-features" run
Updating crates.io index
warning: spurious network error (2 tries remaining): early EOF; class=Net (12); code=Eof (-20)
warning: spurious network error (1 tries remaining): [56] Failure when receiving data from the peer (GnuTLS recv error (-9): Error decoding the received TLS packet.); class=Net (12) # noqa: 204
error: Unable to update registry `crates-io`
Caused by:
failed to fetch `https://github.com/rust-lang/crates.io-index`
Caused by:
network failure seems to have happened
if a proxy or similar is necessary `net.git-fetch-with-cli` may help here
https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli
Caused by:
[18] Transferred a partial file; class=Net (12)
#}
{#
{{ clone_template(['debian-minimal', 'whonix-workstation'], sls_path) }}
{{ clone_template('whonix-workstation', 'electrs-builder', include_create=False) }}
#}

View File

@ -0,0 +1,10 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
base:
'dom0':
- match: nodegroup
- sys-electrs.clone

View File

@ -0,0 +1,133 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
{% if grains['nodename'] != 'dom0' -%}
{% set electrs_obj_type = 'tag' -%}
{% if electrs_obj_type == 'commit' -%}
{% set electrs_obj = '52e3b1907248b8b7f778edc70af9cbac7387a6b6' -%}
{% else -%}
{% set electrs_obj = 'v0.10.3' -%}
{% endif -%}
{% set cfg_me_version = '0.1.1' -%}
{% set cargo_opts = '' -%}
{% if salt['file.file_exists']('/usr/share/whonix/marker') -%}
{% set cargo_opts = '--config net.git-fetch-with-cli=true --config http.proxy=\"socks5h://10.152.152.10:9400\"' -%}
{% endif -%}
include:
- dev.home-cleanup
- dotfiles.copy-x11
- dotfiles.copy-sh
"{{ slsdotpath }}-source-gnupg-home":
file.directory:
- name: /home/user/.gnupg/electrs
- user: user
- group: user
- mode: '0700'
- makedirs: True
"{{ slsdotpath }}-source-save-keys":
file.recurse:
- require:
- file: "{{ slsdotpath }}-source-gnupg-home"
- name: /home/user/.gnupg/electrs/download/
- source: salt://{{ slsdotpath }}/files/server/keys/
- user: user
- group: user
- file_mode: '0600'
- dir_mode: '0700'
- makedirs: True
"{{ slsdotpath }}-source-import-keys":
cmd.run:
- require:
- file: "{{ slsdotpath }}-source-save-keys"
- name: gpg --status-fd=2 --homedir . --import download/*.asc
- cwd: /home/user/.gnupg/electrs
- runas: user
- success_stderr: IMPORT_OK
"{{ slsdotpath }}-source-import-ownertrust":
cmd.run:
- require:
- cmd: "{{ slsdotpath }}-source-import-keys"
- name: gpg --homedir . --import-ownertrust download/otrust.txt
- cwd: /home/user/.gnupg/electrs
- runas: user
"{{ slsdotpath }}-source-makedir-src":
file.directory:
- name: /home/user/src
- user: user
- group: user
- mode: '0755'
- makedirs: True
"{{ slsdotpath }}-source-git-clone":
git.latest:
- name: https://github.com/romanz/electrs
- target: /home/user/src/electrs
- user: user
- force_fetch: True
"{{ slsdotpath }}-source-git-verify-{{ electrs_obj_type }}-{{ electrs_obj }}":
cmd.run:
- require:
- git: "{{ slsdotpath }}-source-git-clone"
- cmd: "{{ slsdotpath }}-source-import-ownertrust"
- env:
- GNUPGHOME: "/home/user/.gnupg/electrs"
- name: git -c gpg.program=gpg2 verify-{{ electrs_obj_type }} "{{ electrs_obj }}"
- cwd: /home/user/src/electrs
- runas: user
"{{ slsdotpath }}-source-git-checkout-{{ electrs_obj_type }}-{{ electrs_obj }}":
cmd.run:
- name: git checkout {{ electrs_obj }}
- require:
- cmd: "{{ slsdotpath }}-source-git-verify-{{ electrs_obj_type }}-{{ electrs_obj }}"
- cwd: /home/user/src/electrs
- runas: user
"{{ slsdotpath }}-source-build-release":
cmd.run:
- require:
- cmd: "{{ slsdotpath }}-source-git-checkout-{{ electrs_obj_type }}-{{ electrs_obj }}"
- env:
- ROCKSDB_INCLUDE_DIR: /usr/include
- ROCKSDB_LIB_DIR: /usr/lib
- name: cargo {{ cargo_opts }} build --locked --release --no-default-features
- cwd: /home/user/src/electrs
- runas: user
"{{ slsdotpath }}-source-install-cfg_me":
cmd.run:
- require:
- cmd: "{{ slsdotpath }}-source-build-release"
- name: cargo {{ cargo_opts }} install --root ~/.local --version {{ cfg_me_version }} cfg_me
- runas: user
"{{ slsdotpath }}-source-build-manpages":
cmd.run:
- require:
- cmd: "{{ slsdotpath }}-source-install-cfg_me"
- name: cfg_me -o /tmp/electrs.1 man
- cwd: /home/user/src/electrs
- runas: user
"{{ slsdotpath }}-copy-files-to-template":
cmd.run:
- require:
- cmd: "{{ slsdotpath }}-source-build-release"
- name: qrexec-client-vm -T -- @default qusal.InstallElectrs /usr/lib/qubes/qfile-agent target/release/electrs /tmp/electrs.1
- cwd: /home/user/src/electrs
- runas: user
{% endif -%}

View File

@ -0,0 +1,9 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
base:
'disp-electrs-builder':
- sys-electrs.configure-builder-source

View File

@ -0,0 +1,12 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
{% if grains['nodename'] != 'dom0' -%}
include:
- .configure-builder-source
{% endif -%}

View File

@ -0,0 +1,9 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
base:
'disp-electrs-builder':
- sys-electrs.configure-builder

View File

@ -0,0 +1,24 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
{% if grains['nodename'] != 'dom0' -%}
"{{ slsdotpath }}-disables-connections-to-random-servers":
cmd.run:
- name: electrum --offline setconfig auto_connect false
- runas: user
"{{ slsdotpath }}-connect-to-one-server-only":
cmd.run:
- name: electrum --offline setconfig oneserver true
- runas: user
"{{ slsdotpath }}-connect-to-server-listening-on-localhost":
cmd.run:
- name: electrum --offline setconfig server 127.0.0.1:50001:t
- runas: user
{% endif -%}

View File

@ -0,0 +1,9 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
base:
'*':
- sys-electrs.configure-client

View File

@ -0,0 +1,41 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
{% if grains['nodename'] != 'dom0' -%}
include:
- dev.home-cleanup
- dotfiles.copy-x11
- dotfiles.copy-sh
- whonix-workstation.configure-offline
"{{ slsdotpath }}-bitcoin-data-directory":
file.directory:
- name: /home/user/.bitcoin
- mode: '0700'
- user: user
- group: user
- makedirs: True
"{{ slsdotpath }}-electrs-configuration":
file.recurse:
- name: /home/user/.electrs/
- source: salt://{{ slsdotpath }}/files/server/conf/
- file_mode: '0600'
- dir_mode: '0700'
- user: user
- group: user
- makedirs: True
"{{ slsdotpath }}-electrs-configuration-directory":
file.directory:
- name: /home/user/.electrs/conf.d
- mode: '0700'
- user: user
- group: user
- makedirs: True
{% endif -%}

View File

@ -0,0 +1,9 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
base:
'sys-electrs':
- sys-electrs.configure

153
salt/sys-electrs/create.sls Normal file
View File

@ -0,0 +1,153 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
{%- from "qvm/template.jinja" import load -%}
include:
- .clone
- sys-bitcoin.create
{% load_yaml as defaults -%}
name: tpl-{{ slsdotpath }}
force: True
require:
- sls: {{ slsdotpath }}.clone
prefs:
- audiovm: ""
{%- endload %}
{{ load(defaults) }}
{% load_yaml as defaults -%}
name: {{ slsdotpath }}
force: True
require:
- sls: {{ slsdotpath }}.clone
present:
- template: tpl-{{ slsdotpath }}
- label: blue
prefs:
- template: tpl-{{ slsdotpath }}
- label: blue
- audiovm: ""
- netvm: ""
- vcpus: 4
- memory: 400
- maxmem: 3000
- autostart: False
- include_in_backups: True
features:
- enable:
- servicevm
- service.bitcoin-client
- disable:
- service.cups
- service.cups-browsed
tags:
- add:
- "bitcoin-client"
{%- endload %}
{{ load(defaults) }}
{% load_yaml as defaults -%}
name: tpl-electrs-builder
force: True
require:
- sls: {{ slsdotpath }}.clone
prefs:
- audiovm: ""
- default_dispvm: ""
## See comment in clone.sls.
{% if salt['cmd.shell']('qvm-features tpl-electrs-builder') == "whonix-ws" %}
tags:
- add:
- "updatevm-sys-bitcoin-gateway"
- del:
- "whonix-updatevm"
{% endif %}
{%- endload %}
{{ load(defaults) }}
{% load_yaml as defaults -%}
name: dvm-electrs-builder
force: True
require:
- qvm: tpl-electrs-builder
present:
- template: tpl-electrs-builder
- label: red
prefs:
- template: tpl-electrs-builder
- label: red
## See comment in clone.sls.
{% if salt['cmd.shell']('qvm-features tpl-electrs-builder') == "whonix-ws" %}
- netvm: sys-bitcoin-gateway
{% else %}
- netvm: "*default*"
{% endif %}
- audiovm: ""
- vcpus: 4
- memory: 400
- maxmem: 800
- autostart: False
- template_for_dispvms: True
- include_in_backups: False
features:
- disable:
- service.cups
- service.cups-browsed
tags:
- add:
- "anon-bitcoin-vm"
- del:
- "anon-vm"
{%- endload %}
{{ load(defaults) }}
{% load_yaml as defaults -%}
name: disp-electrs-builder
force: True
require:
- qvm: dvm-electrs-builder
present:
- template: dvm-electrs-builder
- label: red
- class: DispVM
prefs:
- template: dvm-electrs-builder
- label: red
## See comment in clone.sls.
{% if salt['cmd.shell']('qvm-features tpl-electrs-builder') == "whonix-ws" %}
- netvm: sys-bitcoin-gateway
{% else %}
- netvm: "*default*"
{% endif %}
- audiovm: ""
- vcpus: 4
- memory: 400
- maxmem: 800
- autostart: False
- include_in_backups: False
features:
- disable:
- appmenus-dispvm
- service.cups
- service.cups-browsed
tags:
- add:
- "anon-bitcoin-vm"
- del:
- "anon-vm"
{%- endload %}
{{ load(defaults) }}
"{{ slsdotpath }}-extend-private-volume":
cmd.run:
- require:
- qvm: {{ slsdotpath }}
- name: qvm-volume extend {{ slsdotpath }}:private 200Gi
{% from 'utils/macros/policy.sls' import policy_set with context -%}
{{ policy_set(sls_path, '80') }}

View File

@ -0,0 +1,10 @@
{#
SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
SPDX-License-Identifier: AGPL-3.0-or-later
#}
base:
'dom0':
- match: nodegroup
- sys-electrs.create

View File

@ -0,0 +1,12 @@
# SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
## Do not modify this file, create a new policy with with a lower number in the
## file name instead. For example `30-user.policy`.
qusal.InstallElectrs * disp-electrs-builder @default allow target=tpl-sys-electrs user=root autostart=yes
qusal.InstallElectrs * @anyvm @anyvm deny
qubes.ConnectTCP +50001 @tag:electrum-client @default allow target=sys-electrs
qubes.ConnectTCP * @tag:electrum-client @anyvm deny
## vim:ft=qrexecpolicy

View File

@ -0,0 +1,19 @@
## SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. <ben.grande.b@gmail.com>
##
## SPDX-License-Identifier: AGPL-3.0-or-later
## Main
network = "bitcoin"
cookie_file = "/home/user/.bitcoin/.cookie"
daemon_rpc_addr = "127.0.0.1:8332"
daemon_p2p_addr = "127.0.0.1:8333"
electrum_rpc_addr = "127.0.0.1:50001"
db_dir = "/home/user/.electrs/db"
## Security
index_lookup_limit = 1000
## Logging
server_banner = "Welcome to electrs (Electrum Rust Server)!"
log_filters = "INFO"
timestamp = true

View File

@ -0,0 +1,27 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mFIEWBRWsBMIKoZIzj0DAQcCAwQ40rnHifi2GkPFUfXFjEywVymZtDzPkmMmgCgf
eyU4g3MAIRN945XJ/dpWEZaQNOc4a/XZGbCoHtOXvP/L77c/tBxSb21hbiBaZXlk
ZSA8bWVAcm9tYW56ZXkuZGU+iJAEExMIADgWIQQVyMNXSuTx4l8/NcWHyuX6RpF8
uwUCXQYIMQIbAwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRCHyuX6RpF8u8U2
AP4nnO45eHHrkJ3pykJOo9eLZRig+xBqEkOKn37R9BB/zQD8DnGtsIxRrTPgBUVi
8eG2AfK0PGuEjXbRogOOIU7fTZCIkAQTEwgAIQUCWoqEiAIbAwULCQgHAgYVCAkK
CwIEFgIDAQIeAQIXgAAhCRCHyuX6RpF8uxYhBBXIw1dK5PHiXz81xYfK5fpGkXy7
f38A/jHj5E00xmUrLyGnS81c2at7zKz09D9amU7+v42KTjqgAP9YhyJsPSE71vS3
MV30ksJVF6zEMxhbZULHIM7S0ia9n7QjUm9tYW4gWmV5ZGUgPHJvbWFuLnpleWRl
QGdtYWlsLmNvbT6IiAQTEwgAGQUCWBRWsAILCQIbAwQVCgkIBBYCAwECF4AAIQkQ
h8rl+kaRfLsWIQQVyMNXSuTx4l8/NcWHyuX6RpF8u2YBAP9/rWcfXs5NFnORhj9y
8NWTI2VzxRDojvuR5IHhSGHT4wD6A+QybIChS4Nf5t+2UBZ6QIsgljWn7KMWk6ry
h2y/QI6IiwQTEwgAHAUCWBRWsAILCQIbAwQVCAkKBBYCAwECF4ACHgEAIQkQh8rl
+kaRfLsWIQQVyMNXSuTx4l8/NcWHyuX6RpF8uz/JAQCFt7bxfMZkXa/cZqAoHZUc
MIipC2+At7Bgguv7taDQhgD/Rq5y51LZpv0cOdLPPtKdfC/Omzi4UtVJA1LPi0kZ
H82IhAQTEwgAFQUCWBRWsAILCQIbAwIVCAIWAAIXgAAhCRCHyuX6RpF8uxYhBBXI
w1dK5PHiXz81xYfK5fpGkXy7fscBAPep68dj5O0UMPvOsf1wW9t+FnZRYQfLbnaP
kzPaE1mOAP9Gjo+Cene7/feLUXZfX8tyep+npdUmruCQL5ucpiLYRbhWBFgUVrAS
CCqGSM49AwEHAgMEyc6mujqulvKOnPxaDuL8KqO+M+G0glE4Sb9oXv6oGfSds4Ae
MFKqeX3Lnol0j7F9G1RLlKwBtMPzd5Y6lUmzEwMBCAeIeAQYEwgACQUCWBRWsAIb
DAAhCRCHyuX6RpF8uxYhBBXIw1dK5PHiXz81xYfK5fpGkXy7o/EA/iCdgn0rROTM
vHhS9dO8wH2+hxCKuhTAGXDjvx+yfoLKAP0SZmn2pfB5Wp6Lkm7rzjN7sJ2qzqmq
w+JNEdwSENp7pg==
=9SZC
-----END PGP PUBLIC KEY BLOCK-----

Some files were not shown because too many files have changed in this diff Show More