Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for BIP78 payjoins to .onion receivers #638

Closed
wants to merge 12 commits into from
Closed
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@ For a quick introduction to Joinmarket you can watch [this demonstration](https:
* PayJoin - both [BIP78](https://github.com/bitcoin/bips/blob/master/bip-0078.mediawiki) to pay users of other wallets (e.g. merchants), as well as between two JM wallet users. This is a way to boost fungibility/privacy while paying.
* Protection from [forced address reuse](https://en.bitcoin.it/wiki/Privacy#Forced_address_reuse) attacks.

### Quickstart - RECOMMENDED INSTALLATION METHOD (Linux only)
### Quickstart - RECOMMENDED INSTALLATION METHOD (Linux and macOS only)

Once you've downloaded this repo, either as a tar/zip file, and extracted it, or via `git clone`:

Make sure to validate the signature on the tar/zip file provided on the [release page](https://github.com/Joinmarket-Org/joinmarket-clientserver/releases),
or check the signature in git if you install that way using `git log --show-signature`.

**macOS users**: Make sure that you have Homebrew and Apple's Command Line Tools installed.

./install.sh
(follow instructions on screen; provide sudo password when prompted)
source jmvenv/bin/activate
Expand All @@ -48,7 +50,7 @@ Alternative to this "quickstart": follow the [install guide](docs/INSTALL.md).

### More installation guides

* Installation on MacOS or Windows. Follow [this install guide](docs/INSTALL.md).
* Installation on macOS or Windows. Follow [this install guide](docs/INSTALL.md).
* [Installation guide for RaspiBlitz](https://github.com/openoms/bitcoin-tutorials/blob/master/joinmarket/README.md).
* [Installation guide for RaspiBolt](https://github.com/kristapsk/raspibolt-extras/blob/master/joinmarket.md).
* [Installation guide for Qubes+Whonix](https://github.com/qubenix/qubes-whonix-bitcoin/blob/master/1_joinmarket.md).
Expand Down
100 changes: 79 additions & 21 deletions docs/INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,64 +74,117 @@ command line scripts as explained in the [scripts README](https://github.com/Ada
```
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```
3) Install python3 and libsodium
3) Install automake, libtool, and libsodium
```
brew install python libsodium
brew install automake libtool libsodium
```
4) Create virtualenv "jmvenv"
```sh
pip3 install virtualenv
virtualenv jmvenv
source jmvenv/bin/activate
4) Build secp256k1
```
git clone https://github.com/bitcoin-core/secp256k1
cd secp256k1
git checkout 0d9540b13ffcd7cd44cc361b8744b93d88aa76ba
./autogen.sh
./configure --enable-module-recovery --disable-jni --enable-experimental --enable-module-ecdh --enable-benchmark=no
make
make check
sudo make install
cd ..
rm -rf secp256k1
```
At this point you should see `(jmvenv)` at the beginning of your command prompt.

5) Clone the joinmarket-clientserver repo.
```
git clone https://github.com/Joinmarket-Org/joinmarket-clientserver
cd joinmarket-clientserver
```
6) Setup joinmarket-qt
6) Create virtualenv "jmvenv"
```sh
sudo pip3 install virtualenv
virtualenv jmvenv
source jmvenv/bin/activate
```
At this point you should see `(jmvenv)` at the beginning of your command prompt.

7) Setup joinmarket-qt
```
pip install -r requirements/gui.txt
```
7) Start joinmarket-qt
8) Start joinmarket-qt
```
cd scripts
python joinmarket-qt.py
```

### Installation on Windows
> note: Installing JoinMarket on Windows using the following method requires Windows 10 version 1607 or later.

#### Enable Windows Subsystem for Linux
Before starting, note you need either (a) Bitcoin Core installed on Windows or (b) use a remote connection to Bitcoin Core specified in the `joinmarket.cfg` (explained at the end of this section).

If (a), then note the following two points:

##### Installing Bitcoin Core
If you haven't done so yet, install Bitcoin Core as described [here](https://bitcoin.org/en/full-node#windows-10). After starting it for the first time, it will start the Initial Block Download. JoinMarket cannot be used until this is finished. More information on that can be found [here](https://bitcoin.org/en/full-node#initial-block-downloadibd).

##### Configuring Bitcoin Core
Bitcoin Core needs to be configured to allow JoinMarket to connect to it. From the `Settings` menu choose `Options` and click `Open Configuration File`. Add `server=1`, save and close the file. After that restart Bitcoin Core.

There are currently two choices for installing on Windows; one, directly installing on Windows, requiring the manual addition of a libsodium dependency, or, two, using Ubuntu via the WSL mechanism (which may require additional setup to make the Qt GUI work).

1) [Installation directly on Windows](#installation-directly-on-windows)

2) [Installation using WSL](#installation-using-wsl)

#### Installation directly on Windows

First, if you have not done so, install [Python](https://www.python.org/downloads/windows/) - specifically, the latest Python 3 version. Make sure to choose to install `pip` during the installation (it should be included automatically, but you can choose the custom installation option to choose it).

Be sure to choose the option that allows `python` to be in your PATH variable (you are prompted to do this at the end of the install).

Install Joinmarket, choosing the zip file of the latest [release](https://github.com/JoinMarket-Org/joinmarket-clientserver/releases). You should check the .asc signature file on the zip that you download.

Unzip the `joinmarket-clientserver-x.x.x` (where `x.x.x` is the release number) in any appropriate location.

Using the command prompt in Administrator mode, go to that directory and run the commands:

`pip install -r requirements\base.txt`
`pip install -r requirements\gui.txt`

(the latter is needed for Joinmarket-Qt).

The final step is to manually add the libsodium dependency, as mentioned. Do the following:

Download the file at `https://www.nuget.org/api/v2/package/libsodium` and rename it to `.zip` so that you can unzip it. Once unzipped, find the `libsodium.dll` file at `runtimes\win-x64\native\libsodium.dll` and copy it into `C:\Windows\System` (note this will require Admin rights).

At this point Joinmarket should be ready to run both in command line and Joinmarket-Qt form (using `python joinmarket-qt.py` from the `\scripts` subdirectory of `joinmarket-clientserver`).

From here, go to `Configuring Joinmarket` below.

#### Installation using WSL

> note: The following method requires Windows 10 version 1607 or later.

##### Enable Windows Subsystem for Linux
> note: a more detailed guide can be found [here](https://github.com/michaeltreat/Windows-Subsystem-For-Linux-Setup-Guide/blob/master/readmes/02_WSL_Ubuntu_setup.md).

1. Open the `Control Panel` and navigate to `Programs`, `Programs and Features`, `Turn Windows features on or off`.
2. Select `Windows Subsystem for Linux` and click `OK`.
3. When asked, choose to restart.

#### Install Ubuntu from the Microsoft Store
##### Install Ubuntu from the Microsoft Store
1. Open the `Microsoft Store`, search for `Ubuntu 18.04 LTS` and click `Get`.
> note: other distributions are available, but this is the only one tested
2. When finished downloading click `Launch`.
3. A window should pop up, telling your `Installing, this may take a few minutes...`
4. After installation is done, you'll be asked to provide a `UNIX username` and `UNIX password`. This will be the administrator account for the Ubuntu installation.
5. Finish the installation with updating the software within Ubuntu by typing the command `sudo apt update && sudo apt upgrade -y`. When asked, type the password provided earlier.

#### Installing JoinMarket
##### Installing JoinMarket
At this point you have an (almost) fully featured Linux installation on Windows and you can install JoinMarket using the instructions in the [readme file](../README.md#quickstart) or [Installation on Linux](#installation-on-linux) section of this file.

#### Installing Bitcoin Core
If you haven't done so yet, install Bitcoin Core as described [here](https://bitcoin.org/en/full-node#windows-10). After starting it for the first time, it will start the Initial Block Download. JoinMarket cannot be used until this is finished. More information on that can be found [here](https://bitcoin.org/en/full-node#initial-block-downloadibd).

#### Configuring Bitcoin Core
Bitcoin Core needs to be configured to allow JoinMarket to connect to it. From the `Settings` menu choose `Options` and click `Open Configuration File`. Add `server=1`, save and close the file. After that restart Bitcoin Core.
Once you have finished installing the program via one of the two above methods for Windows, the final step is to configure Joinmarket:

#### Configuring JoinMarket
Lastly we must configure JoinMarket to allow it to connect to Bitcoin Core. Refer to [this](USAGE.md#managing-your-joinmarket-data) section in the usage guide to generate a `joinmarket.cfg` file using `scripts/wallet-tool.py`.

Edit your `joinmarket.cfg` file (in Ubuntu) and replace the following lines in the section `[BLOCKCHAIN]`
Edit your `joinmarket.cfg` file (at `~/.joinmarket` in Ubuntu if you used WSL, or in `C:\Users\<your username>\AppData\Roaming\joinmarket` if not) and replace the following lines in the section `[BLOCKCHAIN]`

```
rpc_user = bitcoin
Expand All @@ -153,6 +206,11 @@ rpc_cookie_file = /mnt/c/Users/Alice/AppData/Roaming/Bitcoin/.cookie
```

#### Running JoinMarket-Qt

If you installed directly on Windows, this should work normally, as explained in the [usage guide](USAGE.md)

If you installed using WSL, the following configuration is necessary:

> note: you need to have installed JoinMarket with Qt support (see [this](../README.md#joinmarket-qt) section in the readme file)
1. In Ubuntu, install additional dependencies `sudo apt install libgl1-mesa-glx`.
2. Download and install [MobaXterm](https://mobaxterm.mobatek.net). This program needs to be running before you can start JoinMarket-Qt. It requires no additional configuration.
Expand Down
10 changes: 10 additions & 0 deletions docs/PAYJOIN.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ The process here is to use the syntax of sendpayment.py:
Notes on this:
* Payjoins BIP78 style are done using the `sendpayment` script (there is no Qt support yet, but it will come later).
* They are done using BIP21 URIs. These can be copy/pasted from a website (e.g. a btcpayserver invoice page), note that double quotes are required because the string contains special characters. Note also that you must see `pj=` in the URI, otherwise payjoin is not supported by that server.
* If the url in `pj=` is `****.onion` it means you must be using Tor, remember to have Tor running on your system and change the configuration (see below) for sock5 port if necessary. If you are running the Tor browser the port is 9150 instead of 9050.
* Don't forget to specify the mixdepth you are spending from with `-m 0`. The payment amount is of course in the URI, along with the address.
* Pay attention to address type; this point is complicated, but: some servers will not be able to match the address type of the sender, and so won't be able to construct sensible Payjoin transactions. In that case they may fallback to the non-Payjoin payment (which is not a disaster). If you want to do a Payjoin with a server that only supports bech32, you will have to create a new Joinmarket wallet, specifying `native=true` in the `POLICY` section of `joinmarket.cfg` before you generate the wallet.

Expand Down Expand Up @@ -191,6 +192,15 @@ max_additional_fee_contribution = default
# this is the minimum satoshis per vbyte we allow in the payjoin
# transaction; note it is decimal, not integer.
min_fee_rate = 1.1


# for payjoins to hidden service endpoints, the socks5 configuration:
onion_socks5_host = localhost
onion_socks5_port = 9050
# in some exceptional case the HS may be SSL configured,
# this feature is not yet implemented in code, but here for the
# future:
hidden_service_ssl = false
```

As the notes mention, you should probably find the defaults here are absolutely fine, and
Expand Down
2 changes: 1 addition & 1 deletion docs/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ First thing to do: go into `scripts/`, and run:
This *should* quit with an error, because the connection to Bitcoin Core is not configured; we'll cover that in the next section.
However, this first run will have automatically created a data directory.
Locate the newly created file `joinmarket.cfg` which will be in your user home directory under `.joinmarket/`.
So on Linux you should find it under `/home/username/.joinmarket/joinmarket.cfg`, and similarly for MacOS and Windows.
So on Linux you should find it under `/home/username/.joinmarket/joinmarket.cfg`, and similarly for macOS and Windows.
You should see the following files and folders for an initial setup:

```
Expand Down
70 changes: 55 additions & 15 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,21 @@ check_exists() {
command -v "$1" > /dev/null
}

# This is needed for systems where GNU is not the default make, like FreeBSD.
if check_exists gmake; then
make=gmake
else
make=make
fi

sha256_verify ()
{
if [[ "$(uname)" == "Darwin" ]]; then
shasum -a 256 -c <<<"$1 $2"
return "$?"
elif [[ "$(uname)" == "FreeBSD" ]]; then
sha256 -c "$1" "$2"
return "$?"
else
sha256sum -c <<<"$1 $2"
return "$?"
Expand All @@ -30,7 +40,7 @@ http_get ()

deps_install ()
{
common_deps=( \
debian_deps=( \
'curl' \
'build-essential' \
'automake' \
Expand All @@ -41,13 +51,20 @@ deps_install ()
'virtualenv' \
'python3-pip' )

darwin_deps=( \
'automake' \
'libtool' )

if ! is_python3; then
echo "Python 2 is no longer supported. Please use a compatible Python 3 version."
return 1
fi

if [[ ${install_os} == 'debian' ]]; then
deb_deps_install "${common_deps[@]}"
deb_deps_install "${debian_deps[@]}"
return "$?"
elif [[ ${install_os} == 'darwin' ]]; then
dar_deps_install "${darwin_deps[@]}"
return "$?"
else
echo "OS can not be determined. Trying to build."
Expand Down Expand Up @@ -76,6 +93,22 @@ deb_deps_install ()
fi
}

dar_deps_install ()
{
dar_deps=( ${@} )
if ! brew install ${dar_deps[@]}; then
return 1
fi
echo "
sudo password required to run :

\`sudo pip3 install virtualenv\`
"
if ! sudo pip3 install virtualenv; then
return 1
fi
}

check_skip_build ()
{
if [[ ${reinstall} == false ]] && [[ -d "$1" ]]; then
Expand Down Expand Up @@ -124,7 +157,7 @@ dep_get ()
openssl_build ()
{
./config shared --prefix="${jm_root}"
make
$make
rm -rf "${jm_root}/ssl" \
"${jm_root}/lib/engines" \
"${jm_root}/lib/pkgconfig/openssl.pc" \
Expand All @@ -133,7 +166,7 @@ openssl_build ()
"${jm_root}/include/openssl" \
"${jm_root}/bin/c_rehash" \
"${jm_root}/bin/openssl"
if ! make test; then
if ! $make test; then
return 1
fi
}
Expand All @@ -153,7 +186,7 @@ openssl_install ()
fi
pushd "${openssl_version}"
if openssl_build; then
make install_sw
$make install_sw
else
return 1
fi
Expand Down Expand Up @@ -202,9 +235,9 @@ libffi_build ()
{
./autogen.sh
./configure --disable-docs --enable-shared --prefix="${jm_root}"
make uninstall
make
if ! make check; then
$make uninstall
$make
if ! $make check; then
return 1
fi
}
Expand All @@ -227,7 +260,7 @@ libffi_install ()
return 1
fi
if libffi_build; then
make install
$make install
else
return 1
fi
Expand Down Expand Up @@ -270,16 +303,16 @@ libsecp256k1_install()

libsodium_build ()
{
make uninstall
make distclean
$make uninstall
$make distclean
./autogen.sh
./configure \
--enable-minimal \
--enable-shared \
--prefix="${jm_root}"
make uninstall
make
if ! make check; then
$make uninstall
$make
if ! $make check; then
return 1
fi
}
Expand All @@ -299,7 +332,7 @@ libsodium_install ()
fi
pushd "${sodium_version}"
if libsodium_build; then
make install
$make install
else
return 1
fi
Expand Down Expand Up @@ -394,6 +427,11 @@ os_is_deb ()
( which apt-get && which dpkg-query ) 2>/dev/null 1>&2
}

os_is_dar ()
{
[[ "$(uname)" == "Darwin" ]]
}

is_python3 ()
{
if [[ ${python} == python3* ]]; then
Expand All @@ -409,6 +447,8 @@ install_get_os ()
{
if os_is_deb; then
echo 'debian'
elif os_is_dar; then
echo 'darwin'
else
echo 'unknown'
fi
Expand Down
Loading