diff --git a/pkgs/default.nix b/pkgs/default.nix index b01c915..b026f3f 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -8,6 +8,7 @@ let self = { hwi = pkgs.callPackage ./hwi { }; pylightning = pkgs.python3Packages.callPackage ./pylightning { }; liquid-swap = pkgs.python3Packages.callPackage ./liquid-swap { }; + joinmarket = pkgs.callPackage ./joinmarket { }; generate-secrets = pkgs.callPackage ./generate-secrets { }; nixops19_09 = pkgs.callPackage ./nixops { }; netns-exec = pkgs.callPackage ./netns-exec { }; diff --git a/pkgs/joinmarket/bencoderpyx/default.nix b/pkgs/joinmarket/bencoderpyx/default.nix new file mode 100644 index 0000000..cc76623 --- /dev/null +++ b/pkgs/joinmarket/bencoderpyx/default.nix @@ -0,0 +1,22 @@ +{ lib, buildPythonPackage, fetchurl, cython, pytest, coverage }: + +buildPythonPackage rec { + pname = "bencoder.pyx"; + version = "2.0.1"; + + src = fetchurl { + url = "https://github.com/whtsky/bencoder.pyx/archive/v${version}.tar.gz"; + sha256 = "f3ff92ac706a7e4692bed5e6cbe205963327f3076f55e408eb948659923eac72"; + }; + + nativeBuildInputs = [ cython ]; + + checkInputs = [ pytest coverage ]; + + meta = with lib; { + description = "A fast bencode implementation in Cython"; + homepage = "https://github.com/whtsky/bencoder.pyx"; + maintainers = with maintainers; [ nixbitcoin ]; + license = licenses.bsd3; + }; +} diff --git a/pkgs/joinmarket/chromalog/default.nix b/pkgs/joinmarket/chromalog/default.nix new file mode 100644 index 0000000..44589a8 --- /dev/null +++ b/pkgs/joinmarket/chromalog/default.nix @@ -0,0 +1,24 @@ +{ lib, buildPythonPackage, fetchFromGitHub, colorama, future, six }: +buildPythonPackage rec { + pname = "chromalog"; + version = "1.0.5"; + + src = fetchFromGitHub { + owner = "freelan-developers"; + repo = "chromalog"; + rev = "${version}"; + sha256 = "0pj4s52rgwlvwkzrj85y92c5r9c84pz8gga45jl5spysrv41y9p0"; + }; + + propagatedBuildInputs = [ colorama future six ]; + + # enable when https://github.com/freelan-developers/chromalog/issues/6 is resolved + doCheck = false; + + meta = with lib; { + description = "Enhance Python with colored logging"; + homepage = "https://github.com/freelan-developers/chromalog"; + maintainers = with maintainers; [ nixbitcoin ]; + license = licenses.mit; + }; +} diff --git a/pkgs/joinmarket/coincurve/default.nix b/pkgs/joinmarket/coincurve/default.nix new file mode 100644 index 0000000..67e9a57 --- /dev/null +++ b/pkgs/joinmarket/coincurve/default.nix @@ -0,0 +1,25 @@ +{ lib, buildPythonPackage, fetchPypi, asn1crypto, cffi, pkg-config, libtool, libffi, requests, gmp }: + +buildPythonPackage rec { + pname = "coincurve"; + version = "13.0.0"; + + src = fetchPypi { + inherit pname version; + sha256 = "1x8dpbq6bwswfyi1g4r421hnswp904l435rf7n6fj7y8q1yn51cr"; + }; + + nativeBuildInputs = [ pkg-config libtool libffi gmp ]; + + propagatedBuildInputs = [ asn1crypto cffi requests ]; + + # enable when https://github.com/ofek/coincurve/issues/47 is resolved + doCheck = false; + + meta = with lib; { + description = "Cross-platform Python CFFI bindings for libsecp256k1"; + homepage = "https://github.com/ofek/coincurve"; + maintainers = with maintainers; [ nixbitcoin ]; + license = licenses.asl20; + }; +} diff --git a/pkgs/joinmarket/default.nix b/pkgs/joinmarket/default.nix new file mode 100644 index 0000000..ea8f04e --- /dev/null +++ b/pkgs/joinmarket/default.nix @@ -0,0 +1,68 @@ +{ stdenv, fetchurl, python3 }: + +let + version = "0.7.0"; + src = fetchurl { + url = "https://github.com/JoinMarket-Org/joinmarket-clientserver/archive/v${version}.tar.gz"; + sha256 = "0ha73n3y5lykyj3pl97a619sxd2zz0lb32s5c61wm0l1h47v9l1g"; + }; + + python = python3.override { + packageOverrides = self: super: let + joinmarketPkg = pkg: self.callPackage pkg { inherit version src; }; + in { + joinmarketbase = joinmarketPkg ./jmbase; + joinmarketclient = joinmarketPkg ./jmclient; + joinmarketbitcoin = joinmarketPkg ./jmbitcoin; + joinmarketdaemon = joinmarketPkg ./jmdaemon; + + chromalog = self.callPackage ./chromalog {}; + bencoderpyx = self.callPackage ./bencoderpyx {}; + coincurve = self.callPackage ./coincurve {}; + urldecode = self.callPackage ./urldecode {}; + python-bitcointx = self.callPackage ./python-bitcointx {}; + secp256k1 = self.callPackage ./secp256k1 {}; + }; + }; + + runtimePackages = with python.pkgs; [ + joinmarketbase + joinmarketclient + joinmarketbitcoin + joinmarketdaemon + ]; + + pythonEnv = python.withPackages (_: runtimePackages); +in +stdenv.mkDerivation { + pname = "joinmarket"; + inherit version src; + + buildInputs = [ pythonEnv ]; + + buildCommand = '' + mkdir -p $src-unpacked $out/bin + tar xzf $src --strip 1 -C $src-unpacked + + # add-utxo.py -> bin/jm-add-utxo + cpBin() { + cp $src-unpacked/scripts/$1 $out/bin/jm-''${1%.py} + } + cp $src-unpacked/scripts/joinmarketd.py $out/bin/joinmarketd + cpBin add-utxo.py + cpBin convert_old_wallet.py + cpBin receive-payjoin.py + cpBin sendpayment.py + cpBin sendtomany.py + cpBin tumbler.py + cpBin wallet-tool.py + cpBin yg-privacyenhanced.py + + chmod +x -R $out/bin + patchShebangs $out/bin + ''; + + passthru = { + inherit python runtimePackages pythonEnv; + }; +} diff --git a/pkgs/joinmarket/get-sha256.sh b/pkgs/joinmarket/get-sha256.sh new file mode 100755 index 0000000..6bdb149 --- /dev/null +++ b/pkgs/joinmarket/get-sha256.sh @@ -0,0 +1,25 @@ +#! /usr/bin/env nix-shell +#! nix-shell -i bash -p git gnupg +set -euo pipefail + +TMPDIR="$(mktemp -d -p /tmp)" +trap "rm -rf $TMPDIR" EXIT +cd $TMPDIR + +echo "Fetching latest release" +git clone https://github.com/joinmarket-org/joinmarket-clientserver 2> /dev/null +cd joinmarket-clientserver +latest=$(git describe --tags `git rev-list --tags --max-count=1`) +echo "Latest release is ${latest}" + +# GPG verification +export GNUPGHOME=$TMPDIR +echo "Fetching Adam Gibson's key" +gpg --keyserver hkps://keyserver.ubuntu.com --recv-keys 2B6FC204D9BF332D062B461A141001A1AF77F20B 2> /dev/null +echo "Verifying latest release" +git verify-tag ${latest} + +echo "tag: ${latest}" +# The prefix option is necessary because GitHub prefixes the archive contents in this format +echo "sha256: $(nix-hash --type sha256 --flat --base32 \ + <(git archive --format tar.gz --prefix=joinmarket-clientserver-"${latest//v}"/ ${latest}))" diff --git a/pkgs/joinmarket/jmbase/default.nix b/pkgs/joinmarket/jmbase/default.nix new file mode 100644 index 0000000..d1fdfe6 --- /dev/null +++ b/pkgs/joinmarket/jmbase/default.nix @@ -0,0 +1,16 @@ +{ version, src, lib, buildPythonPackage, fetchurl, future, twisted, service-identity, chromalog }: + +buildPythonPackage rec { + pname = "joinmarketbase"; + inherit version src; + + postUnpack = "sourceRoot=$sourceRoot/jmbase"; + + propagatedBuildInputs = [ future twisted service-identity chromalog ]; + + meta = with lib; { + homepage = "https://github.com/Joinmarket-Org/joinmarket-clientserver"; + maintainers = with maintainers; [ nixbitcoin ]; + license = licenses.gpl3; + }; +} diff --git a/pkgs/joinmarket/jmbitcoin/default.nix b/pkgs/joinmarket/jmbitcoin/default.nix new file mode 100644 index 0000000..b61228d --- /dev/null +++ b/pkgs/joinmarket/jmbitcoin/default.nix @@ -0,0 +1,18 @@ +{ version, src, lib, buildPythonPackage, fetchurl, future, coincurve, urldecode, pyaes, python-bitcointx, secp256k1, joinmarketbase }: + +buildPythonPackage rec { + pname = "joinmarketbitcoin"; + inherit version src; + + postUnpack = "sourceRoot=$sourceRoot/jmbitcoin"; + + propagatedBuildInputs = [ future coincurve urldecode pyaes python-bitcointx secp256k1 ]; + + checkInputs = [ joinmarketbase ]; + + meta = with lib; { + homepage = "https://github.com/Joinmarket-Org/joinmarket-clientserver"; + maintainers = with maintainers; [ nixbitcoin ]; + license = licenses.gpl3; + }; +} diff --git a/pkgs/joinmarket/jmclient/default.nix b/pkgs/joinmarket/jmclient/default.nix new file mode 100644 index 0000000..dd8d4a3 --- /dev/null +++ b/pkgs/joinmarket/jmclient/default.nix @@ -0,0 +1,20 @@ +{ version, src, lib, buildPythonPackage, fetchurl, future, configparser, joinmarketbase, mnemonic, argon2_cffi, bencoderpyx, pyaes, joinmarketbitcoin, txtorcon }: + +buildPythonPackage rec { + pname = "joinmarketclient"; + inherit version src; + + postUnpack = "sourceRoot=$sourceRoot/jmclient"; + + checkInputs = [ joinmarketbitcoin txtorcon ]; + + # configparser may need to be compiled with python_version<"3.2" + propagatedBuildInputs = [ future configparser joinmarketbase mnemonic argon2_cffi bencoderpyx pyaes ]; + + meta = with lib; { + description = "Client library for Bitcoin coinjoins"; + homepage = "https://github.com/Joinmarket-Org/joinmarket-clientserver"; + maintainers = with maintainers; [ nixbitcoin ]; + license = licenses.gpl3; + }; +} diff --git a/pkgs/joinmarket/jmdaemon/default.nix b/pkgs/joinmarket/jmdaemon/default.nix new file mode 100644 index 0000000..0a7493e --- /dev/null +++ b/pkgs/joinmarket/jmdaemon/default.nix @@ -0,0 +1,17 @@ +{ version, src, lib, buildPythonPackage, fetchurl, future, txtorcon, pyopenssl, libnacl, joinmarketbase }: + +buildPythonPackage rec { + pname = "joinmarketdaemon"; + inherit version src; + + postUnpack = "sourceRoot=$sourceRoot/jmdaemon"; + + propagatedBuildInputs = [ future txtorcon pyopenssl libnacl joinmarketbase ]; + + meta = with lib; { + description = "Client library for Bitcoin coinjoins"; + homepage = "https://github.com/Joinmarket-Org/joinmarket-clientserver"; + maintainers = with maintainers; [ nixbitcoin ]; + license = licenses.gpl3; + }; +} diff --git a/pkgs/joinmarket/python-bitcointx/default.nix b/pkgs/joinmarket/python-bitcointx/default.nix new file mode 100644 index 0000000..213f5d8 --- /dev/null +++ b/pkgs/joinmarket/python-bitcointx/default.nix @@ -0,0 +1,27 @@ +{ lib, buildPythonPackage, fetchurl, secp256k1, openssl }: + +buildPythonPackage rec { + pname = "python-bitcointx"; + version = "1.1.1"; + + src = fetchurl { + url = "https://github.com/Simplexum/${pname}/archive/${pname}-v${version}.tar.gz"; + sha256 = "35edd694473517508367338888633954eaa91b2622b3caada8fd3030ddcacba2"; + }; + + patchPhase = '' + for path in core/secp256k1.py tests/test_load_secp256k1.py; do + substituteInPlace "bitcointx/$path" \ + --replace "ctypes.util.find_library('secp256k1')" "'${secp256k1}/lib/libsecp256k1.so'" + done + substituteInPlace bitcointx/core/key.py \ + --replace "ctypes.util.find_library('ssl')" "'${openssl.out}/lib/libssl.so'" + ''; + + meta = with lib; { + description = "Interface to Bitcoin transaction data structures"; + homepage = "https://github.com/Simplexum/python-bitcointx"; + maintainers = with maintainers; [ nixbitcoin ]; + license = licenses.gpl3; + }; +} diff --git a/pkgs/joinmarket/python-bitcointx/get-sha256.sh b/pkgs/joinmarket/python-bitcointx/get-sha256.sh new file mode 100755 index 0000000..34ab4c1 --- /dev/null +++ b/pkgs/joinmarket/python-bitcointx/get-sha256.sh @@ -0,0 +1,24 @@ +#! /usr/bin/env nix-shell +#! nix-shell -i bash -p git gnupg +set -euo pipefail + +TMPDIR="$(mktemp -d -p /tmp)" +trap "rm -rf $TMPDIR" EXIT +cd $TMPDIR + +echo "Fetching latest release" +git clone https://github.com/simplexum/python-bitcointx 2> /dev/null +cd python-bitcointx +latest=$(git describe --tags `git rev-list --tags --max-count=1`) +echo "Latest release is ${latest}" + +# GPG verification +export GNUPGHOME=$TMPDIR +echo "Fetching Dimitry Pethukov's Key" +gpg --keyserver hkps://keyserver.ubuntu.com --recv-keys B17A35BBA187395784E2A6B32301D26BDC15160D 2> /dev/null +echo "Verifying latest release" +git verify-commit ${latest} + +echo "tag: ${latest}" +# The prefix option is necessary because GitHub prefixes the archive contents in this format +echo "sha256: $(git archive --format tar.gz --prefix=python-bitcointx-"${latest}"/ ${latest} | sha256sum | cut -d\ -f1)" diff --git a/pkgs/joinmarket/secp256k1/default.nix b/pkgs/joinmarket/secp256k1/default.nix new file mode 100644 index 0000000..a52adb3 --- /dev/null +++ b/pkgs/joinmarket/secp256k1/default.nix @@ -0,0 +1,28 @@ +{ stdenv, fetchFromGitHub, autoreconfHook }: + +let inherit (stdenv.lib) optionals; in + +stdenv.mkDerivation { + pname = "secp256k1"; + + version = "2019-10-11"; + + src = fetchFromGitHub { + owner = "bitcoin-core"; + repo = "secp256k1"; + rev = "0d9540b13ffcd7cd44cc361b8744b93d88aa76ba"; + sha256 = "05zwhv8ffzrfdzqbsb4zm4kjdbjxqy5jh9r83fic0qpk2mkvc2i2"; + }; + + nativeBuildInputs = [ autoreconfHook ]; + + configureFlags = ["--enable-module-recovery" "--disable-jni" "--enable-experimental" "--enable-module-ecdh" "--enable-benchmark=no" ]; + + meta = with stdenv.lib; { + description = "Optimized C library for EC operations on curve secp256k1"; + homepage = "https://github.com/bitcoin-core/secp256k1"; + license = with licenses; [ mit ]; + maintainers = with maintainers; [ nixbitcoin ]; + platforms = with platforms; unix; + }; +} diff --git a/pkgs/joinmarket/urldecode/default.nix b/pkgs/joinmarket/urldecode/default.nix new file mode 100644 index 0000000..93f1a76 --- /dev/null +++ b/pkgs/joinmarket/urldecode/default.nix @@ -0,0 +1,16 @@ +{ lib, buildPythonPackage, fetchPypi }: +buildPythonPackage rec { + pname = "urldecode"; + version = "0.1"; + + src = fetchPypi { + inherit pname version; + sha256 = "0w8my7kdwxppsfzzi1b2cxhypm6r1fsrnb2hnd752axq4gfsddjj"; + }; + + meta = with lib; { + description = "A simple function to decode an encoded url"; + homepage = "https://github.com/jennyq/urldecode"; + maintainers = with maintainers; [ nixbitcoin ]; + }; +}