aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am3
-rw-r--r--contrib/README.md10
-rw-r--r--contrib/debian/README.md21
-rw-r--r--contrib/debian/bitcoin-qt.desktop14
-rw-r--r--contrib/debian/bitcoin-qt.install6
-rw-r--r--contrib/debian/bitcoin-qt.lintian-overrides2
-rw-r--r--contrib/debian/bitcoin-qt.manpages1
-rw-r--r--contrib/debian/bitcoin-qt.protocol11
-rw-r--r--contrib/debian/bitcoin-tx.bash-completion1
-rw-r--r--contrib/debian/bitcoin-tx.install1
-rw-r--r--contrib/debian/bitcoin-tx.manpages1
-rw-r--r--contrib/debian/bitcoind.bash-completion2
-rw-r--r--contrib/debian/bitcoind.examples1
-rw-r--r--contrib/debian/bitcoind.install2
-rw-r--r--contrib/debian/bitcoind.lintian-overrides2
-rw-r--r--contrib/debian/bitcoind.manpages2
-rw-r--r--contrib/debian/changelog578
-rw-r--r--contrib/debian/compat1
-rw-r--r--contrib/debian/control70
-rw-r--r--contrib/debian/gbp.conf5
-rw-r--r--contrib/debian/patches/README3
-rw-r--r--contrib/debian/patches/series1
-rwxr-xr-xcontrib/debian/rules23
-rw-r--r--contrib/debian/source/format1
-rw-r--r--contrib/debian/watch5
-rw-r--r--contrib/rpm/README.md185
-rw-r--r--contrib/rpm/bitcoin-0.12.0-libressl.patch24
-rw-r--r--contrib/rpm/bitcoin.fc8
-rw-r--r--contrib/rpm/bitcoin.if157
-rw-r--r--contrib/rpm/bitcoin.spec442
-rw-r--r--contrib/rpm/bitcoin.te81
-rw-r--r--doc/bips.md3
-rw-r--r--doc/init.md2
-rw-r--r--share/examples/bitcoin.conf (renamed from contrib/debian/examples/bitcoin.conf)0
-rw-r--r--src/Makefile.am2
-rw-r--r--src/Makefile.test.include1
-rw-r--r--src/bench/coin_selection.cpp2
-rw-r--r--src/bench/mempool_eviction.cpp3
-rw-r--r--src/bitcoind.cpp2
-rw-r--r--src/chainparams.cpp25
-rw-r--r--src/chainparams.h6
-rw-r--r--src/init.cpp2
-rw-r--r--src/interfaces/node.cpp2
-rw-r--r--src/net.cpp1
-rw-r--r--src/netaddress.cpp3
-rw-r--r--src/rpc/blockchain.cpp168
-rw-r--r--src/scheduler.h17
-rw-r--r--src/script/descriptor.cpp566
-rw-r--r--src/script/descriptor.h102
-rw-r--r--src/script/sign.cpp30
-rw-r--r--src/script/sign.h13
-rw-r--r--src/span.h20
-rw-r--r--src/test/blockencodings_tests.cpp6
-rw-r--r--src/test/descriptor_tests.cpp163
-rw-r--r--src/test/mempool_tests.cpp7
-rw-r--r--src/test/miner_tests.cpp3
-rw-r--r--src/test/policyestimator_tests.cpp1
-rw-r--r--src/test/scheduler_tests.cpp44
-rw-r--r--src/txmempool.cpp4
-rw-r--r--src/txmempool.h6
-rw-r--r--src/util.cpp10
-rw-r--r--src/validationinterface.h15
-rw-r--r--src/wallet/wallet.cpp8
-rwxr-xr-xtest/functional/feature_includeconf.py8
-rwxr-xr-xtest/functional/rpc_scantxoutset.py60
-rwxr-xr-xtest/functional/wallet_groups.py26
66 files changed, 1156 insertions, 1839 deletions
diff --git a/Makefile.am b/Makefile.am
index f3f3302fce..10dda65b21 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -42,8 +42,7 @@ DIST_CONTRIB = $(top_srcdir)/contrib/bitcoin-cli.bash-completion \
$(top_srcdir)/contrib/bitcoin-tx.bash-completion \
$(top_srcdir)/contrib/bitcoind.bash-completion \
$(top_srcdir)/contrib/init \
- $(top_srcdir)/contrib/install_db4.sh \
- $(top_srcdir)/contrib/rpm
+ $(top_srcdir)/contrib/install_db4.sh
DIST_SHARE = \
$(top_srcdir)/share/genbuild.sh \
$(top_srcdir)/share/rpcauth
diff --git a/contrib/README.md b/contrib/README.md
index bcf9186fa1..8915919766 100644
--- a/contrib/README.md
+++ b/contrib/README.md
@@ -21,9 +21,10 @@ Utility to generate the pnSeed[] array that is compiled into the client.
Build Tools and Keys
---------------------
-### [Debian](/contrib/debian) ###
-Contains files used to package bitcoind/bitcoin-qt
-for Debian-based Linux systems. If you compile bitcoind/bitcoin-qt yourself, there are some useful files here.
+### Packaging ###
+The [Debian](/contrib/debian) subfolder contains the copyright file.
+
+All other packaging related files can be found in the [bitcoin-core/packaging](https://github.com/bitcoin-core/packaging) repository.
### [Gitian-descriptors](/contrib/gitian-descriptors) ###
Files used during the gitian build process. For more information about gitian, see the [the Bitcoin Core documentation repository](https://github.com/bitcoin-core/docs).
@@ -34,9 +35,6 @@ PGP keys used for signing Bitcoin Core [Gitian release](/doc/release-process.md)
### [MacDeploy](/contrib/macdeploy) ###
Scripts and notes for Mac builds.
-### [RPM](/contrib/rpm) ###
-RPM spec file for building bitcoin-core on RPM based distributions.
-
### [Gitian-build](/contrib/gitian-build.py) ###
Script for running full Gitian builds.
diff --git a/contrib/debian/README.md b/contrib/debian/README.md
deleted file mode 100644
index fab9cc2381..0000000000
--- a/contrib/debian/README.md
+++ /dev/null
@@ -1,21 +0,0 @@
-
-Debian
-====================
-This directory contains files used to package bitcoind/bitcoin-qt
-for Debian-based Linux systems. If you compile bitcoind/bitcoin-qt yourself, there are some useful files here.
-
-## bitcoin: URI support ##
-
-
-bitcoin-qt.desktop (Gnome / Open Desktop)
-To install:
-
- sudo desktop-file-install bitcoin-qt.desktop
- sudo update-desktop-database
-
-If you build yourself, you will either need to modify the paths in
-the .desktop file or copy or symlink your bitcoin-qt binary to `/usr/bin`
-and the `../../share/pixmaps/bitcoin128.png` to `/usr/share/pixmaps`
-
-bitcoin-qt.protocol (KDE)
-
diff --git a/contrib/debian/bitcoin-qt.desktop b/contrib/debian/bitcoin-qt.desktop
deleted file mode 100644
index 8b31222648..0000000000
--- a/contrib/debian/bitcoin-qt.desktop
+++ /dev/null
@@ -1,14 +0,0 @@
-[Desktop Entry]
-Version=1.0
-Name=Bitcoin Core
-Comment=Connect to the Bitcoin P2P Network
-Comment[de]=Verbinde mit dem Bitcoin peer-to-peer Netzwerk
-Comment[fr]=Bitcoin, monnaie virtuelle cryptographique pair à pair
-Comment[tr]=Bitcoin, eşten eşe kriptografik sanal para birimi
-Exec=bitcoin-qt %u
-Terminal=false
-Type=Application
-Icon=bitcoin128
-MimeType=x-scheme-handler/bitcoin;
-Categories=Office;Finance;P2P;Network;Qt;
-StartupWMClass=Bitcoin-qt
diff --git a/contrib/debian/bitcoin-qt.install b/contrib/debian/bitcoin-qt.install
deleted file mode 100644
index e0b32373be..0000000000
--- a/contrib/debian/bitcoin-qt.install
+++ /dev/null
@@ -1,6 +0,0 @@
-usr/local/bin/bitcoin-qt usr/bin
-share/pixmaps/bitcoin32.xpm usr/share/pixmaps
-share/pixmaps/bitcoin16.xpm usr/share/pixmaps
-share/pixmaps/bitcoin128.png usr/share/pixmaps
-debian/bitcoin-qt.desktop usr/share/applications
-debian/bitcoin-qt.protocol usr/share/kde4/services/
diff --git a/contrib/debian/bitcoin-qt.lintian-overrides b/contrib/debian/bitcoin-qt.lintian-overrides
deleted file mode 100644
index 7fb230eca8..0000000000
--- a/contrib/debian/bitcoin-qt.lintian-overrides
+++ /dev/null
@@ -1,2 +0,0 @@
-# Linked code is Expat - only Debian packaging is GPL-2+
-bitcoin-qt: possible-gpl-code-linked-with-openssl
diff --git a/contrib/debian/bitcoin-qt.manpages b/contrib/debian/bitcoin-qt.manpages
deleted file mode 100644
index 9a3cc31c09..0000000000
--- a/contrib/debian/bitcoin-qt.manpages
+++ /dev/null
@@ -1 +0,0 @@
-doc/man/bitcoin-qt.1
diff --git a/contrib/debian/bitcoin-qt.protocol b/contrib/debian/bitcoin-qt.protocol
deleted file mode 100644
index 014588d536..0000000000
--- a/contrib/debian/bitcoin-qt.protocol
+++ /dev/null
@@ -1,11 +0,0 @@
-[Protocol]
-exec=bitcoin-qt '%u'
-protocol=bitcoin
-input=none
-output=none
-helper=true
-listing=
-reading=false
-writing=false
-makedir=false
-deleting=false
diff --git a/contrib/debian/bitcoin-tx.bash-completion b/contrib/debian/bitcoin-tx.bash-completion
deleted file mode 100644
index 7acb0b0aea..0000000000
--- a/contrib/debian/bitcoin-tx.bash-completion
+++ /dev/null
@@ -1 +0,0 @@
-contrib/bitcoin-tx.bash-completion bitcoin-tx
diff --git a/contrib/debian/bitcoin-tx.install b/contrib/debian/bitcoin-tx.install
deleted file mode 100644
index 2c21052a68..0000000000
--- a/contrib/debian/bitcoin-tx.install
+++ /dev/null
@@ -1 +0,0 @@
-usr/local/bin/bitcoin-tx usr/bin
diff --git a/contrib/debian/bitcoin-tx.manpages b/contrib/debian/bitcoin-tx.manpages
deleted file mode 100644
index 861d49d070..0000000000
--- a/contrib/debian/bitcoin-tx.manpages
+++ /dev/null
@@ -1 +0,0 @@
-doc/man/bitcoin-tx.1
diff --git a/contrib/debian/bitcoind.bash-completion b/contrib/debian/bitcoind.bash-completion
deleted file mode 100644
index 5c69d78fbb..0000000000
--- a/contrib/debian/bitcoind.bash-completion
+++ /dev/null
@@ -1,2 +0,0 @@
-contrib/bitcoind.bash-completion bitcoind
-contrib/bitcoin-cli.bash-completion bitcoin-cli
diff --git a/contrib/debian/bitcoind.examples b/contrib/debian/bitcoind.examples
deleted file mode 100644
index 4ded67d98e..0000000000
--- a/contrib/debian/bitcoind.examples
+++ /dev/null
@@ -1 +0,0 @@
-debian/examples/bitcoin.conf
diff --git a/contrib/debian/bitcoind.install b/contrib/debian/bitcoind.install
deleted file mode 100644
index 798ea851f6..0000000000
--- a/contrib/debian/bitcoind.install
+++ /dev/null
@@ -1,2 +0,0 @@
-usr/local/bin/bitcoind usr/bin
-usr/local/bin/bitcoin-cli usr/bin
diff --git a/contrib/debian/bitcoind.lintian-overrides b/contrib/debian/bitcoind.lintian-overrides
deleted file mode 100644
index 3f9f140bd8..0000000000
--- a/contrib/debian/bitcoind.lintian-overrides
+++ /dev/null
@@ -1,2 +0,0 @@
-# Linked code is Expat - only Debian packaging is GPL-2+
-bitcoind: possible-gpl-code-linked-with-openssl
diff --git a/contrib/debian/bitcoind.manpages b/contrib/debian/bitcoind.manpages
deleted file mode 100644
index bab644ece1..0000000000
--- a/contrib/debian/bitcoind.manpages
+++ /dev/null
@@ -1,2 +0,0 @@
-doc/man/bitcoind.1
-doc/man/bitcoin-cli.1
diff --git a/contrib/debian/changelog b/contrib/debian/changelog
deleted file mode 100644
index 33dab9b638..0000000000
--- a/contrib/debian/changelog
+++ /dev/null
@@ -1,578 +0,0 @@
-bitcoin (0.14.1-trusty4) trusty; urgency=medium
-
- * Re-enable UPnP support.
-
- -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Fri, 05 May 2017 13:28:00 -0400
-
-bitcoin (0.14.1-trusty3) trusty; urgency=medium
-
- * Build with qt5 if we are on a non-Ubuntu (ie non-Unity) distro.
-
- -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Thu, 04 May 2017 17:13:00 -0400
-
-bitcoin (0.14.1-trusty2) trusty; urgency=medium
-
- * Bump minimum boost version in deps.
-
- -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Thu, 04 May 2017 17:12:00 -0400
-
-bitcoin (0.14.1-trusty1) trusty; urgency=medium
-
- * New upstream release.
-
- -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Sat, 22 Apr 2017 17:10:00 -0400
-
-bitcoin (0.14.0-trusty1) trusty; urgency=medium
-
- * New upstream release.
-
- -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Wed, 08 Mar 2017 10:30:00 -0500
-
-bitcoin (0.13.2-trusty1) trusty; urgency=medium
-
- * New upstream release.
-
- -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Thu, 05 Jan 2017 09:59:00 -0500
-
-bitcoin (0.13.1-trusty2) trusty; urgency=medium
-
- * Revert to Qt4, due to https://github.com/bitcoin/bitcoin/issues/9038
-
- -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Mon, 31 Oct 2016 11:16:00 -0400
-
-bitcoin (0.13.1-trusty1) trusty; urgency=medium
-
- * New upstream release.
- * Backport updated bitcoin-qt.desktop from upstream master
- * Add zmq dependency
- * Switch to Qt5 (breaks precise, but that was already broken by C++11)
-
- -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Thu, 27 Oct 2016 17:32:00 -0400
-
-bitcoin (0.13.0-trusty1) trusty; urgency=medium
-
- * New upstream release.
-
- -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Sun, 04 Sep 2016 22:09:00 -0400
-
-bitcoin (0.12.1-trusty1) trusty; urgency=medium
-
- * New upstream release.
-
- -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Mon, 18 Apr 2016 14:26:00 -0700
-
-bitcoin (0.12.0-trusty6) trusty; urgency=medium
-
- * Fix program-options dep.
-
- -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Fri, 25 Mar 2016 21:41:00 -0700
-
-bitcoin (0.12.0-trusty5) trusty; urgency=medium
-
- * Test explicit --with-gui
-
- -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Tue, 23 Feb 2015 23:25:00 -0800
-
-bitcoin (0.12.0-trusty4) trusty; urgency=medium
-
- * Fix libevent-dev dep.
-
- -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Tue, 23 Feb 2015 23:25:00 -0800
-
-bitcoin (0.12.0-trusty3) trusty; urgency=medium
-
- * Fix precise boost dep.
-
- -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Tue, 23 Feb 2015 19:55:00 -0800
-
-bitcoin (0.12.0-trusty2) trusty; urgency=medium
-
- * Fix libevent dep.
-
- -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Tue, 23 Feb 2015 19:53:00 -0800
-
-bitcoin (0.12.0-trusty1) trusty; urgency=medium
-
- * New upstream release
- * Various updates to contrib/debian were merged, a few were not
-
- -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Tue, 23 Feb 2015 19:29:00 -0800
-
-bitcoin (0.11.2-trusty1) trusty; urgency=low
-
- * New upstream release.
-
- -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Fri, 13 Nov 2015 18:39:00 -0800
-
-bitcoin (0.11.1-trusty2) trusty; urgency=low
-
- * Remove minupnpc builddep.
-
- -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Wed, 14 Oct 2015 23:06:00 -1000
-
-bitcoin (0.11.1-trusty1) trusty; urgency=high
-
- * New upstream release.
- * Disable all UPnP support.
-
- -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Wed, 14 Oct 2015 13:57:00 -1000
-
-bitcoin (0.11.0-precise1) precise; urgency=medium
-
- * New upstream release.
-
- -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Tue, 14 Jul 2015 14:39:00 -1000
-
-bitcoin (0.10.2-precise1) precise; urgency=medium
-
- * New upstream release.
-
- -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Mon, 29 Jun 2015 17:33:00 -1000
-
-bitcoin (0.10.1-precise3) precise; urgency=medium
-
- * Fix build dep (include python).
-
- -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Tue, 5 May 2015 09:28:00 -1000
-
-bitcoin (0.10.1-precise2) precise; urgency=medium
-
- * Fix miniupnpc dep.
-
- -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Tue, 5 May 2015 00:33:00 -1000
-
-bitcoin (0.10.1-precise1) precise; urgency=medium
-
- * New upstream release.
-
- -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Tue, 5 May 2015 00:07:00 -1000
-
-bitcoin (0.10.0-precise1) precise; urgency=medium
-
- * New upstream releases.
-
- -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Wed, 18 Feb 2015 13:22:00 -1000
-
-bitcoin (0.9.4-precise1) precise; urgency=high
-
- * New upstream releases.
-
- -- Matt Corallo (laptop - only while traveling) <matt@mattcorallo.com> Mon, 12 Jan 2015 23:30:00 -1000
-
-bitcoin (0.9.3-precise1) precise; urgency=medium
-
- * New upstream releases.
-
- -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Fri, 26 Sep 2014 12:01:00 -0700
-
-bitcoin (0.9.1-precise1) precise; urgency=medium
-
- * New upstream release.
- * Backport pull #4019
-
- -- Matt Corallo <matt@bluematt.me> Sat, 19 Apr 2014 17:29:00 -0400
-
-bitcoin (0.9.0-precise1) precise; urgency=medium
-
- * New upstream release.
-
- -- Matt Corallo <matt@bluematt.me> Thu, 20 Mar 2014 13:10:00 -0400
-
-bitcoin (0.8.6-precise1) precise; urgency=medium
-
- * New upstream release.
- * Make .desktop paths non-fixed (suggested by prusnak@github)
-
- -- Matt Corallo <matt@bluematt.me> Fri, 13 Dec 2013 13:31:00 -0400
-
-bitcoin (0.8.5-precise1) precise; urgency=medium
-
- * New upstream release.
-
- -- Matt Corallo <matt@bluematt.me> Sun, 15 Sep 2013 14:02:00 -0400
-
-bitcoin (0.8.4-precise1) precise; urgency=medium
-
- * New upstream release.
-
- -- Matt Corallo <matt@bluematt.me> Wed, 4 Sep 2013 10:25:00 -0400
-
-bitcoin (0.8.3-natty1) natty; urgency=low
-
- * New upstream release.
-
- -- Matt Corallo <matt@bluematt.me> Wed, 26 Jun 2013 00:18:00 +0100
-
-bitcoin (0.8.2-natty1) natty; urgency=low
-
- * New upstream release.
-
- -- Matt Corallo <matt@bluematt.me> Wed, 29 Mar 2013 23:23:00 +0100
-
-bitcoin (0.8.1-natty3) natty; urgency=low
-
- * New pixmaps
-
- -- Jonas Schnelli <jonas.schnelli@include7.ch> Mon, 13 May 2013 16:14:00 +0100
-
-bitcoin (0.8.1-natty2) natty; urgency=low
-
- * Remove dumb broken launcher script
-
- -- Matt Corallo <matt@bluematt.me> Sun, 24 Mar 2013 20:01:00 -0400
-
-bitcoin (0.8.1-natty1) natty; urgency=low
-
- * New upstream release.
-
- -- Matt Corallo <matt@bluematt.me> Tue, 19 Mar 2013 13:03:00 -0400
-
-bitcoin (0.8.0-natty1) natty; urgency=low
-
- * New upstream release.
-
- -- Matt Corallo <matt@bluematt.me> Sat, 23 Feb 2013 16:01:00 -0500
-
-bitcoin (0.7.2-natty1) natty; urgency=low
-
- * New upstream release.
-
- -- Matt Corallo <matt@bluematt.me> Sat, 15 Dec 2012 10:59:00 -0400
-
-bitcoin (0.7.1-natty1) natty; urgency=low
-
- * New upstream release.
-
- -- Matt Corallo <matt@bluematt.me> Wed, 24 Oct 2012 15:06:00 -0400
-
-bitcoin (0.7.0-natty1) natty; urgency=low
-
- * New upstream release.
-
- -- Matt Corallo <matt@bluematt.me> Mon, 17 Sep 2012 13:45:00 +0200
-
-bitcoin (0.6.3-natty1) natty; urgency=low
-
- * New upstream release.
-
- -- Matt Corallo <matt@bluematt.me> Mon, 25 Jun 2012 23:47:00 +0200
-
-bitcoin (0.6.2-natty1) natty; urgency=low
-
- * Update package description and launch scripts.
-
- -- Matt Corallo <matt@bluematt.me> Sat, 2 Jun 2012 16:41:00 +0200
-
-bitcoin (0.6.2-natty0) natty; urgency=low
-
- * New upstream release.
-
- -- Matt Corallo <matt@bluematt.me> Tue, 8 May 2012 16:27:00 -0500
-
-bitcoin (0.6.1-natty0) natty; urgency=low
-
- * New upstream release.
-
- -- Matt Corallo <matt@bluematt.me> Sun, 6 May 2012 20:09:00 -0500
-
-bitcoin (0.6.0-natty0) natty; urgency=low
-
- * New upstream release.
- * Add GNOME/KDE support for bitcoin-qt's bitcoin: URI support.
- Thanks to luke-jr for the KDE .protocol file.
-
- -- Matt Corallo <matt@bluematt.me> Sat, 31 Mar 2012 15:35:00 -0500
-
-bitcoin (0.5.3-natty1) natty; urgency=low
-
- * Mark for upload to PPA.
-
- -- Matt Corallo <matt@bluematt.me> Wed, 14 Mar 2012 23:06:00 -0400
-
-bitcoin (0.5.3-natty0) natty; urgency=low
-
- * New upstream release.
-
- -- Luke Dashjr <luke+bitcoin+deb@dashjr.org> Tue, 10 Jan 2012 15:57:00 -0500
-
-bitcoin (0.5.2-natty1) natty; urgency=low
-
- * Remove mentions on anonymity in package descriptions and manpage.
- These should never have been there, bitcoin isnt anonymous without
- a ton of work that virtually no users will ever be willing and
- capable of doing
-
- -- Matt Corallo <matt@bluematt.me> Sat, 7 Jan 2012 13:37:00 -0500
-
-bitcoin (0.5.2-natty0) natty; urgency=low
-
- * New upstream release.
-
- -- Luke Dashjr <luke+bitcoin+deb@dashjr.org> Fri, 16 Dec 2011 17:57:00 -0500
-
-bitcoin (0.5.1-natty0) natty; urgency=low
-
- * New upstream release.
-
- -- Matt Corallo <matt@bluematt.me> Fri, 16 Dec 2011 13:27:00 -0500
-
-bitcoin (0.5.0-natty0) natty; urgency=low
-
- * New upstream release.
-
- -- Matt Corallo <matt@bluematt.me> Mon, 21 Nov 2011 11:32:00 -0500
-
-bitcoin (0.5.0~rc7-natty0) natty; urgency=low
-
- * New upstream release candidate.
-
- -- Matt Corallo <matt@bluematt.me> Sun, 20 Nov 2011 17:08:00 -0500
-
-bitcoin (0.5.0~rc3-natty0) natty; urgency=low
-
- * New upstream release candidate.
- * Don't set rpcpassword for bitcoin-qt.
-
- -- Matt Corallo <matt@bluematt.me> Tue, 8 Nov 2011 11:56:00 -0400
-
-bitcoin (0.5.0~rc1-natty1) natty; urgency=low
-
- * Add test_bitcoin to build test
- * Fix clean
- * Remove uneccessary build-dependancies
-
- -- Matt Corallo <matt@bluematt.me> Wed, 26 Oct 2011 14:37:18 -0400
-
-bitcoin (0.5.0~rc1-natty0) natty; urgency=low
-
- * Mark for natty
- * Fix broken build
- * Fix copyright listing
- * Remove bitcoin: URL handler until bitcoin actually has support for it (Oops)
-
- -- Matt Corallo <matt@bluematt.me> Wed, 26 Oct 2011 14:37:18 -0400
-
-bitcoin (0.5.0~rc1-2) experimental; urgency=low
-
- * Add bitcoin-qt
-
- -- Matt Corallo <matt@bluematt.me> Tue, 25 Oct 2011 15:24:18 -0400
-
-bitcoin (0.5.0~rc1-1) experimental; urgency=low
-
- * New upstream prerelease.
- * Add Github as alternate upstream source in watch file.
- * Stop build-depending on libcrypto++-dev, and drop patch 1000:
- Upstream no longer use crypto++.
- * Drop patch 1003: Upstream builds dynamic by default now.
- * Update copyright file: Drop notes on longer included sources.
-
- -- Jonas Smedegaard <dr@jones.dk> Fri, 14 Oct 2011 00:16:18 +0200
-
-bitcoin (0.4.0-1) unstable; urgency=low
-
- * New upstream release.
- * Stop repackaging source tarballs: No DFSG-violating stripping left.
- * Update copyright file:
- + Add Github URL to Source.
- * Drop dpkg-source local-options hint: Declared options are default
- since dpkg-source 1.16.1.
- + Add irc URL to Upstream-Contact.
- + Add comment on Bitcoin Developers to catch-all Files section.
- + Add Files sections for newly readded src/cryptopp/* (new custom
- BSD-like license), and newly added doc/build-osx.txt and
- src/makefile.osx (Expat).
- * Bump debhelper compatibility level to 7.
- * Suppress binary icns and gpg files.
- * Enable regression tests:
- + Build-depend on libboost-test-dev.
- + Extend patch 1003 to also dynamically link test binary.
- + Build and invoke test binary unless tests are disabled.
- * Tighten build-dependency on cdbs: Recent version needed to support
- debhelper 7.
- * Relax build-depend unversioned on debhelper: needed version
- satisfied even in oldstable.
- * Stop suppress optional build-dependencies: Satisfied in stable.
- Build-depend on devscripts (enabling copyright-check).
-
- -- Jonas Smedegaard <dr@jones.dk> Wed, 05 Oct 2011 01:48:53 +0200
-
-bitcoin (0.3.24~dfsg-1) unstable; urgency=low
-
- * New upstream release.
-
- [ Jonas Smedegaard ]
- * Improve various usage hints:
- + Explicitly mention in long description that bitcoind contains
- daemon and command-line interface.
- + Extend README.Debian with section on lack of GUI, and add primary
- headline.
- + Avoid installing upstream README: contains no parts relevant for
- Debian usage.
- Thanks to richard for suggestions (see bug#629443).
- * Favor final releases over prereleases in rules and watch file.
- Thanks to Jan Dittberner.
- * Track -src (not -linux) tarballs in rules and watch file.
- Thanks to Jan Dittberner.
- * Drop patches 1004 and 1005 (integrated upstream) and simplify
- CXXFLAGS in rules file.
- * Stop stripping no longer included source-less binaries from upstream
- tarballs.
-
- [ Jan Dittberner ]
- * refresh debian/patches/1000_use_system_crypto++.patch
-
- -- Jonas Smedegaard <dr@jones.dk> Tue, 19 Jul 2011 15:08:54 +0200
-
-bitcoin (0.3.21~dfsg-2) unstable; urgency=low
-
- * Enable UPNP support:
- + Drop patch 1006.
- + Build-depend on libminiupnpc-dev.
- Thanks to Matt Corallo.
-
- -- Jonas Smedegaard <dr@jones.dk> Sat, 28 May 2011 15:52:44 +0200
-
-bitcoin (0.3.21~dfsg-1) unstable; urgency=low
-
- * New upstream release.
- * Refresh patches.
- * Drop patch 1002: no longer needed, as upstream use pkgconfig now.
- * Add patch 1006 to really unset USE_UPNP as aparently intended.
- * Adjust cleanup rule to preserve .gitignore files.
- * Update copyright file:
- + Bump format to draft 174 of DEP-5.
- + Shorten comments.
- * Bump policy compliance to standards-version 3.9.2.
- * Shorten Vcs-Browser paragraph in control file.
- * Fix mention daemon (not CLI tools) in short description.
- * Stop conflicting with or replace bitcoin-cli: Only transitional, no
- longer needed.
- * Link against unversioned berkeleydb. Update NEWS and README.Debian
- accordingly (and improve wording while at it).
- Closes: Bug#621425. Thanks to Ondřej Surý.
- * This release also implicitly updates linkage against libcrypto++,
- which closes: bug#626953, #627024.
- * Disable linkage against not yet Debian packaged MiniUPnP.
- * Silence seemingly harmless noise about unused variables.
-
- -- Jonas Smedegaard <dr@jones.dk> Tue, 17 May 2011 15:31:24 +0200
-
-bitcoin (0.3.20.2~dfsg-2) unstable; urgency=medium
-
- * Fix have wrapper script execute real binary (not loop executing
- itself).
- Closes: bug#617290. Thanks to Philippe Gauthier and Etienne Laurin.
- * Set urgency=medium as the only (user-exposed) binary is useless
- without this fix and has been for some time.
-
- -- Jonas Smedegaard <dr@jones.dk> Wed, 16 Mar 2011 09:11:06 +0100
-
-bitcoin (0.3.20.2~dfsg-1) unstable; urgency=low
-
- * New upstream release.
- * Fix provide and replace former package name bitcoin-cli.
- Closes: bug#618439. Thanks to Shane Wegner.
-
- -- Jonas Smedegaard <dr@jones.dk> Tue, 15 Mar 2011 11:41:43 +0100
-
-bitcoin (0.3.20.01~dfsg-1) unstable; urgency=low
-
- * New upstream release.
-
- [ Micah Anderson ]
- * Add myself as uploader.
-
- [ Jonas Smedegaard ]
- * Add wrapper for bitcoind to ease initial startup.
- * Update patches:
- + Drop patch 2002: Applied upstream.
- + Add patch 1005 to add phtread linker option.
- Closes: bug#615619. Thanks to Shane Wegner.
- + Refresh patches.
- * Extend copyright years in rules file header.
- * Rewrite copyright file using draft svn166 of DEP5 format.
- * Rename binary package to bitcoind (from bincoin-cli).
- Closes: bug#614025. Thanks to Luke-Jr.
-
- -- Jonas Smedegaard <dr@jones.dk> Tue, 01 Mar 2011 15:55:04 +0100
-
-bitcoin (0.3.19~dfsg-6) unstable; urgency=low
-
- * Fix override agressive optimizations.
- * Fix tighten build-dependencies to really fit backporting to Lenny:
- + Add fallback build-dependency on libdb4.6++-dev.
- + Tighten unversioned Boost build-dependencies to recent versions,
- To force use of versioned Boost when backporting to Lenny.
- ...needs more love, though: actual build fails.
-
- -- Jonas Smedegaard <dr@jones.dk> Mon, 17 Jan 2011 19:48:35 +0100
-
-bitcoin (0.3.19~dfsg-5) unstable; urgency=low
-
- * Fix lower Boost fallback-build-dependencies to 1.35, really
- available in Lenny.
- * Correct comment in rules file regarding reason for versioned Boost
- fallback-build-dependency.
- * Add patch 2002 adding -mt decoration to Boost flags, to ease
- backporting to Lenny.
- * Respect DEB_BUILD_OPTIONS, and suppress arch-specific optimizations:
- + Add patch 1004 to allow overriding optimization flags.
- + Set optimization flags conditionally at build time.
- + Drop patch 2002 unconditionally suppressing arch-optimizations.
-
- -- Jonas Smedegaard <dr@jones.dk> Mon, 17 Jan 2011 16:04:48 +0100
-
-bitcoin (0.3.19~dfsg-4) unstable; urgency=low
-
- [ Micah Anderson ]
- * Provide example bitcoin.conf.
- * Add bitcoind(1) and bitcoin.conf(5) man pages.
-
- [ Jonas Smedegaard ]
- * Ease backporting:
- + Suppress optional build-dependencies.
- + Add fallback build-dependencies on the most recent Boost libs
- available in Lenny (where unversioned Boost libs are missing).
- * Add Micah as copyright holder for manpages, licensed as GPL-3+.
- * Bump copyright format to Subversion candidate draft 162 of DEP5.
-
- -- Jonas Smedegaard <dr@jones.dk> Mon, 17 Jan 2011 14:00:48 +0100
-
-bitcoin (0.3.19~dfsg-3) unstable; urgency=low
-
- * Document in copyright file files excluded from repackaged source.
- * Update copyright file:
- + Bump DEP5 format hint to Subversion draft rev. 153.
- + Consistently wrap at 72 chars.
- + Refer to GPL-2 file (not GPL symlink).
- * Link against Berkeley DB 4.8 (not 4.7):
- + Build-depend on libdb4.8++-dev (and on on libdb4.7++-dev).
- + Suggest libdb4.8-util and db4.7-util.
- + Add README.Debian note on (untested) upgrade routine.
- + Add NEWS entry on changed db version, referring to README.Debian.
-
- -- Jonas Smedegaard <dr@jones.dk> Fri, 07 Jan 2011 22:50:57 +0100
-
-bitcoin (0.3.19~dfsg-2) unstable; urgency=low
-
- * Adjust build options to use optimized miner only for amd64. Fixes
- FTBFS on i386 (and other archs, if compiling anywhere else at all).
- * Avoid static linking.
- * Adjust patch 2001 to avoid only arch-specific optimizations (keep
- -O3).
- * Extend long description to mention disk consumption and initial use
- of IRC.
- All of above changes thanks to Helmuth Grohne.
- * Add lintian override regarding OpenSSL and GPL: Linked code is Expat
- - only Debian packaging is GPL-2+.
-
- -- Jonas Smedegaard <dr@jones.dk> Wed, 29 Dec 2010 00:27:54 +0100
-
-bitcoin (0.3.19~dfsg-1) unstable; urgency=low
-
- [ Jonas Smedegaard ]
- * Initial release.
- Closes: bug#578157.
-
- -- Jonas Smedegaard <dr@jones.dk> Tue, 28 Dec 2010 15:49:22 +0100
diff --git a/contrib/debian/compat b/contrib/debian/compat
deleted file mode 100644
index 7f8f011eb7..0000000000
--- a/contrib/debian/compat
+++ /dev/null
@@ -1 +0,0 @@
-7
diff --git a/contrib/debian/control b/contrib/debian/control
deleted file mode 100644
index 0d6ad25e24..0000000000
--- a/contrib/debian/control
+++ /dev/null
@@ -1,70 +0,0 @@
-Source: bitcoin
-Section: utils
-Priority: optional
-Maintainer: Matt Corallo <matt@mattcorallo.com>
-Uploaders: Matt Corallo <matt@mattcorallo.com>
-Build-Depends: debhelper,
- devscripts,
- automake,
- libtool,
- bash-completion,
- libdb4.8++-dev,
- libssl-dev,
- pkg-config,
- libevent-dev,
- libboost-system1.48-dev | libboost-system-dev (>> 1.47),
- libboost-filesystem1.48-dev | libboost-filesystem-dev (>> 1.47),
- libboost-program-options1.48-dev | libboost-program-options-dev (>> 1.47),
- libboost-thread1.48-dev | libboost-thread-dev (>> 1.47),
- libboost-test1.48-dev | libboost-test-dev (>> 1.47),
- libboost-chrono1.48-dev | libboost-chrono-dev (>> 1.47),
- libminiupnpc8-dev | libminiupnpc-dev,
- qt4-qmake, libqt4-dev,
- qttools5-dev-tools, qttools5-dev,
- libqrencode-dev,
- libprotobuf-dev, protobuf-compiler,
- python,
- libzmq3-dev
-Standards-Version: 3.9.2
-Homepage: https://bitcoincore.org/
-Vcs-Git: git://github.com/bitcoin/bitcoin.git
-Vcs-Browser: https://github.com/bitcoin/bitcoin
-
-Package: bitcoind
-Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}
-Description: peer-to-peer network based digital currency - daemon
- Bitcoin is a free open source peer-to-peer electronic cash system that
- is completely decentralized, without the need for a central server or
- trusted parties. Users hold the crypto keys to their own money and
- transact directly with each other, with the help of a P2P network to
- check for double-spending.
- .
- This package provides the daemon, bitcoind, and the CLI tool
- bitcoin-cli to interact with the daemon.
-
-Package: bitcoin-qt
-Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}
-Description: peer-to-peer network based digital currency - Qt GUI
- Bitcoin is a free open source peer-to-peer electronic cash system that
- is completely decentralized, without the need for a central server or
- trusted parties. Users hold the crypto keys to their own money and
- transact directly with each other, with the help of a P2P network to
- check for double-spending.
- .
- This package provides Bitcoin-Qt, a GUI for Bitcoin based on Qt.
-
-Package: bitcoin-tx
-Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}
-Description: peer-to-peer digital currency - standalone transaction tool
- Bitcoin is a free open source peer-to-peer electronic cash system that
- is completely decentralized, without the need for a central server or
- trusted parties. Users hold the crypto keys to their own money and
- transact directly with each other, with the help of a P2P network to
- check for double-spending.
- .
- This package provides bitcoin-tx, a command-line transaction creation
- tool which can be used without a bitcoin daemon. Some means of
- exchanging minimal transaction data with peers is still required.
diff --git a/contrib/debian/gbp.conf b/contrib/debian/gbp.conf
deleted file mode 100644
index a7281f94b2..0000000000
--- a/contrib/debian/gbp.conf
+++ /dev/null
@@ -1,5 +0,0 @@
-# Configuration file for git-buildpackage and friends
-
-[DEFAULT]
-pristine-tar = True
-sign-tags = True
diff --git a/contrib/debian/patches/README b/contrib/debian/patches/README
deleted file mode 100644
index 80c1584376..0000000000
--- a/contrib/debian/patches/README
+++ /dev/null
@@ -1,3 +0,0 @@
-0xxx: Grabbed from upstream development.
-1xxx: Possibly relevant for upstream adoption.
-2xxx: Only relevant for official Debian release.
diff --git a/contrib/debian/patches/series b/contrib/debian/patches/series
deleted file mode 100644
index 8b13789179..0000000000
--- a/contrib/debian/patches/series
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/contrib/debian/rules b/contrib/debian/rules
deleted file mode 100755
index 6885e38521..0000000000
--- a/contrib/debian/rules
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/make -f
-# -*- mode: makefile; coding: utf-8 -*-
-
-#DEB_MAKE_CHECK_TARGET = test_bitcoin
-#build/bitcoind::
-# $(if $(filter nocheck,$(DEB_BUILD_OPTIONS)),,src/test_bitcoin)
-
-%:
- dh --with bash-completion $@
-
-override_dh_auto_clean:
- if [ -f Makefile ]; then $(MAKE) distclean; fi
- rm -rf Makefile.in aclocal.m4 configure src/Makefile.in src/bitcoin-config.h.in src/build-aux src/qt/Makefile.in src/qt/test/Makefile.in src/test/Makefile.in
-
-QT=$(shell dpkg-vendor --derives-from Ubuntu && echo qt4 || echo qt5)
-
-# Yea, autogen should be run on the source archive, but I like doing git archive
-override_dh_auto_configure:
- ./autogen.sh
- ./configure --with-gui=$(QT)
-
-override_dh_auto_test:
- make check
diff --git a/contrib/debian/source/format b/contrib/debian/source/format
deleted file mode 100644
index 163aaf8d82..0000000000
--- a/contrib/debian/source/format
+++ /dev/null
@@ -1 +0,0 @@
-3.0 (quilt)
diff --git a/contrib/debian/watch b/contrib/debian/watch
deleted file mode 100644
index 4d9e0cfa57..0000000000
--- a/contrib/debian/watch
+++ /dev/null
@@ -1,5 +0,0 @@
-# Run the "uscan" command to check for upstream updates and more.
-version=3
-# use qa.debian.org redirector; see man uscan
-opts=uversionmangle=s/(\d)(alpha|beta|rc)/$1~$2/,dversionmangle=s/~dfsg\d*// \
- http://githubredir.debian.net/github/bitcoin/bitcoin v(.*).tar.gz
diff --git a/contrib/rpm/README.md b/contrib/rpm/README.md
deleted file mode 100644
index e1e0745fd6..0000000000
--- a/contrib/rpm/README.md
+++ /dev/null
@@ -1,185 +0,0 @@
-RPM Spec File Notes
--------------------
-
-The RPM spec file provided here is for Bitcoin-Core 0.12.0 and builds on CentOS
-7 with either the CentOS provided OpenSSL library or with LibreSSL as packaged
-at [LibreLAMP.com](https://librelamp.com/). It should hopefully not be too
-difficult to port the RPM spec file to most RPM based Linux distributions.
-
-When porting the spec file to build for a particular distribution, there are
-some important notes.
-
-## Sources
-
-It is considered good form for all sources to reference a URL where the source
-can be downloaded.
-
-Sources 0-9 should be reserved for source code tarballs. `Source0` should
-reference the release tarball available from https://bitcoin.org/bin/ and
-`Source1` should reference the BerkeleyDB source.
-
-Sources 10-99 are for source files that are maintained in the
-[Bitcoin git repository](https://github.com/bitcoin/bitcoin) but are not part of
-the release tarball. Most of these will reside in the `contrib` sub-directory.
-
-Sources 10-19 should be reserved for miscellaneous configuration files.
-Currently only `Source10` is used, for the example `bitcoin.conf` file.
-
-Sources 20-29 should be reserved for man pages. Currently only `Source20`
-through `Source23` are used.
-
-Sources 30-39 should be reserved for SELinux related files. Currently only
-`Source30` through `Source32` are used. Until those files are in a tagged
-release, the full URL specified in the RPM spec file will not work. You can get
-them from the git repository where you retrieved this file.
-
-Sources 100+ are for files that are not source tarballs and are not maintained
-in the bitcoin git repository. At present only an SVG version of the Bitcoin
-icon is used.
-
-## Patches
-
-In general, patches should be avoided. When a packager feels a patch is
-necessary, the packager should bring the problem to the attention of the bitcoin
-developers so that an official fix to the issue can make it into the next
-release.
-
-### Patch0 bitcoin-0.12.0-libressl.patch
-
-This patch is only needed if building against LibreSSL. LibreSSL is not the
-standard TLS library on most Linux distributions. The patch will likely not be
-needed when 0.12.1 is released, a proper fix is already in the Bitcoin git
-master branch.
-
-## BuildRequires
-
-The packages specified in the `BuildRequires` are specified according to the
-package naming convention currently used in CentOS 7 and EPEL for CentOS 7. You
-may need to change some of the package names for other distributions. This is
-most likely to be the case with the Qt packages.
-
-## BerkeleyDB
-
-The `build-unix.md` file recommends building against BerkeleyDB 4.8.30. Even if
-that is the version your Linux distribution ships with, it probably is a good
-idea to build Bitcoin Core against a static version of that library compiled
-according to the instructions in the `build-unix.md` file so that any changes
-the distribution may make in the future will not result in a problem for users.
-
-The problem that can exist, clients built against different versions of
-BerkeleyDB may not be able read each other's `wallet.dat` file which can make it
-difficult for a user to recover from backup in the event of a system failure.
-
-## Graphical User Interface and Qt Version
-
-The RPM spec file will by default build the GUI client linked against the Qt5
-libraries. If you wish instead to link against the Qt4 libraries you need to
-pass the switch `-D '_use_qt4 1'` at build time to the `rpmbuild` or `mock`
-command used to build the packages.
-
-If you would prefer not to build the GUI at all, you can pass the switch
-`-D '_no_gui 1'` to the `rpmbuild` or `mock` build command.
-
-## Desktop and KDE Files
-
-The desktop and KDE meta files are created in the spec file itself with the
-`cat` command. This is done to allow easy distribution specific changes without
-needing to use any patches. A specific timestamp is given to the files so that
-it does not they do not appear to have been updated every time the package is
-built. If you do make changes to them, you probably should update timestamp
-assigned to them in the `touch` command that specifies the timestamp.
-
-## SVG, PNG, and XPM Icons
-
-The `bitcoin.svg` file is from the source listed as `Source100`. It is used as
-the source for the PNG and XPM files. The generated PNG and XPM files are given
-the same timestamp as the source SVG file as a means of indicating they are
-derived from it.
-
-## Systemd
-
-This spec file assumes the target distribution uses systemd. That really only
-matters for the `bitcoin-server` package. At this point, most RPM based
-distributions that still receive vendor updates do in fact use systemd.
-
-The files to control the service are created in the RPM spec file itself using
-the `cat` command. This is done to make it easy to modify for other
-distributions that may implement things differently without needing to patch
-source. A specific timestamp is given to the files so that they do not appear
-to have been updated every time the package is built. If you do make changes to
-them, you probably should update the timestamp assigned to them in the `touch`
-command that specifies the timestamp.
-
-## SELinux
-
-The `bitcoin-server` package should have SELinux support. How to properly do
-that *may* vary by distribution and version of distribution.
-
-The SELinux stuff in this RPM spec file *should* be correct for CentOS, RHEL,
-and Fedora but it would be a good idea to review it before building the package
-on other distributions.
-
-## Tests
-
-The `%check` section takes a very long time to run. If your build system has a
-time limit for package build, you may need to make an exception for this
-package. On CentOS 7 the `%check` section completes successfully with both
-OpenSSL and LibreSSL, a failure really does mean something is wrong.
-
-## LibreSSL Build Notes
-
-To build against LibreSSL you will need to pass the switch
-`-D '_use_libressl 1'` to the `rpmbuild` or `mock` command or the spec file will
-want the OpenSSL development files.
-
-### LibreSSL and Boost
-
-LibreSSL (and some newer builds of OpenSSL) do not have support for SSLv3. This
-can cause issues with the Boost package if the Boost package has not been
-patched accordingly. On those distributions, you will either need to build
-Bitcoin-Core against OpenSSL or use a patched version of Boost in the build
-system.
-
-As SSLv3 is no longer safe, distributions that have not patched Boost to work
-with TLS libraries that do not support SSLv3 should have bug reports filed
-against the Boost package. This bug report has already been filed for RHEL 7 but
-it may need to be filed for other distributions.
-
-A patch for Boost: https://github.com/boostorg/asio/pull/23/files
-
-## ZeroMQ
-
-At this time, this RPM spec file does not support the ZeroMQ build options. A
-suitable version of ZeroMQ is not available for the platform this spec file was
-developed on (CentOS 7).
-
-## Legacy Credit
-
-This RPM spec file is largely based upon the work of Michael Hampton at
-[Ringing Liberty](https://www.ringingliberty.com/bitcoin/). He has been
-packaging Bitcoin for Fedora at least since 2012.
-
-Most of the differences between his packaging and this package are stylistic in
-nature. The major differences:
-
-1. He builds from a github tagged release rather than a release tarball. This
-should not result in different source code.
-
-2. He does not build BerkeleyDB but instead uses the BerkeleyDB provided by the
-Linux distribution. For the distributions he packages for, they currently all
-use the same version of BerkeleyDB so that difference is *probably* just
-academic.
-
-3. As of his 10.11.2 package he did not allow for building against LibreSSL,
-specifying a build without the Qt GUI, or specifying which version of the Qt
-libraries to use.
-
-4. I renamed the `bitcoin` package that contains the Qt GUI to `bitcoin-core` as
-that appears to be how the general population refers to it, in contrast to
-`bitcoin-xt` or `bitcoin-classic`. I wanted to make sure the general population
-knows what they are getting when installing the GUI package.
-
-As far as minor differences, I generally prefer to assign the file permissions
-in the `%files` portion of an RPM spec file rather than specifying the
-permissions of a file during `%install` and other minor things like that
-are largely just cosmetic.
diff --git a/contrib/rpm/bitcoin-0.12.0-libressl.patch b/contrib/rpm/bitcoin-0.12.0-libressl.patch
deleted file mode 100644
index 555614a06d..0000000000
--- a/contrib/rpm/bitcoin-0.12.0-libressl.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-diff -ur bitcoin-0.12.0.orig/src/init.cpp bitcoin-0.12.0/src/init.cpp
---- bitcoin-0.12.0.orig/src/init.cpp 2015-12-31 16:00:00.000000000 -0800
-+++ bitcoin-0.12.0/src/init.cpp 2016-02-23 06:03:47.133227757 -0800
-@@ -1075,7 +1075,7 @@
- if (fPrintToDebugLog)
- OpenDebugLog();
-
--#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
-+#if defined(LIBRESSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x10100000L)
- LogPrintf("Using OpenSSL version %s\n", SSLeay_version(SSLEAY_VERSION));
- #else
- LogPrintf("Using OpenSSL version %s\n", OpenSSL_version(OPENSSL_VERSION));
-diff -ur bitcoin-0.12.0.orig/src/qt/rpcconsole.cpp bitcoin-0.12.0/src/qt/rpcconsole.cpp
---- bitcoin-0.12.0.orig/src/qt/rpcconsole.cpp 2015-12-31 16:00:00.000000000 -0800
-+++ bitcoin-0.12.0/src/qt/rpcconsole.cpp 2016-02-23 15:09:42.881126841 -0800
-@@ -264,7 +264,7 @@
-
- // set library version labels
-
--#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
-+#if defined(LIBRESSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x10100000L)
- ui->openSSLVersion->setText(SSLeay_version(SSLEAY_VERSION));
- #else
- ui->openSSLVersion->setText(OpenSSL_version(OPENSSL_VERSION));
diff --git a/contrib/rpm/bitcoin.fc b/contrib/rpm/bitcoin.fc
deleted file mode 100644
index 6f5eef6375..0000000000
--- a/contrib/rpm/bitcoin.fc
+++ /dev/null
@@ -1,8 +0,0 @@
-/usr/bin/bitcoin-cli -- gen_context(system_u:object_r:bitcoin_exec_t,s0)
-/usr/sbin/bitcoind -- gen_context(system_u:object_r:bitcoin_exec_t,s0)
-/usr/lib(64)?/bitcoin/bitcoind -- gen_context(system_u:object_r:bitcoin_exec_t,s0)
-
-/etc/bitcoin(/.*)? gen_context(system_u:object_r:bitcoin_conf_t,s0)
-/var/lib/bitcoin(/.*)? gen_context(system_u:object_r:bitcoin_var_lib_t,s0)
-
-(/var)?/run/bitcoind(/.*)? gen_context(system_u:object_r:bitcoin_var_run_t,s0)
diff --git a/contrib/rpm/bitcoin.if b/contrib/rpm/bitcoin.if
deleted file mode 100644
index b206866cc5..0000000000
--- a/contrib/rpm/bitcoin.if
+++ /dev/null
@@ -1,157 +0,0 @@
-
-## <summary>policy for bitcoin</summary>
-
-
-########################################
-## <summary>
-## Transition to bitcoin.
-## </summary>
-## <param name="domain">
-## <summary>
-## Domain allowed to transition.
-## </summary>
-## </param>
-#
-interface(`bitcoin_domtrans',`
- gen_require(`
- type bitcoin_t, bitcoin_exec_t;
- ')
-
- corecmd_search_bin($1)
- domtrans_pattern($1, bitcoin_exec_t, bitcoin_t)
-')
-
-
-########################################
-## <summary>
-## Execute bitcoin server in the bitcoin domain.
-## </summary>
-## <param name="domain">
-## <summary>
-## Domain allowed access.
-## </summary>
-## </param>
-#
-interface(`bitcoin_initrc_domtrans',`
- gen_require(`
- type bitcoin_initrc_exec_t;
- ')
-
- init_labeled_script_domtrans($1, bitcoin_initrc_exec_t)
-')
-
-
-########################################
-## <summary>
-## Search bitcoin lib directories.
-## </summary>
-## <param name="domain">
-## <summary>
-## Domain allowed access.
-## </summary>
-## </param>
-#
-interface(`bitcoin_search_lib',`
- gen_require(`
- type bitcoin_var_lib_t;
- ')
-
- allow $1 bitcoin_var_lib_t:dir search_dir_perms;
- files_search_var_lib($1)
-')
-
-########################################
-## <summary>
-## Read bitcoin lib files.
-## </summary>
-## <param name="domain">
-## <summary>
-## Domain allowed access.
-## </summary>
-## </param>
-#
-interface(`bitcoin_read_lib_files',`
- gen_require(`
- type bitcoin_var_lib_t;
- ')
-
- files_search_var_lib($1)
- read_files_pattern($1, bitcoin_var_lib_t, bitcoin_var_lib_t)
-')
-
-########################################
-## <summary>
-## Manage bitcoin lib files.
-## </summary>
-## <param name="domain">
-## <summary>
-## Domain allowed access.
-## </summary>
-## </param>
-#
-interface(`bitcoin_manage_lib_files',`
- gen_require(`
- type bitcoin_var_lib_t;
- ')
-
- files_search_var_lib($1)
- manage_files_pattern($1, bitcoin_var_lib_t, bitcoin_var_lib_t)
-')
-
-########################################
-## <summary>
-## Manage bitcoin lib directories.
-## </summary>
-## <param name="domain">
-## <summary>
-## Domain allowed access.
-## </summary>
-## </param>
-#
-interface(`bitcoin_manage_lib_dirs',`
- gen_require(`
- type bitcoin_var_lib_t;
- ')
-
- files_search_var_lib($1)
- manage_dirs_pattern($1, bitcoin_var_lib_t, bitcoin_var_lib_t)
-')
-
-
-########################################
-## <summary>
-## All of the rules required to administrate
-## a bitcoin environment
-## </summary>
-## <param name="domain">
-## <summary>
-## Domain allowed access.
-## </summary>
-## </param>
-## <param name="role">
-## <summary>
-## Role allowed access.
-## </summary>
-## </param>
-## <rolecap/>
-#
-interface(`bitcoin_admin',`
- gen_require(`
- type bitcoin_t;
- type bitcoin_initrc_exec_t;
- type bitcoin_var_lib_t;
- ')
-
- allow $1 bitcoin_t:process { ptrace signal_perms };
- ps_process_pattern($1, bitcoin_t)
-
- bitcoin_initrc_domtrans($1)
- domain_system_change_exemption($1)
- role_transition $2 bitcoin_initrc_exec_t system_r;
- allow $2 system_r;
-
- files_search_var_lib($1)
- admin_pattern($1, bitcoin_var_lib_t)
-
-')
-
diff --git a/contrib/rpm/bitcoin.spec b/contrib/rpm/bitcoin.spec
deleted file mode 100644
index 7c4d933ee0..0000000000
--- a/contrib/rpm/bitcoin.spec
+++ /dev/null
@@ -1,442 +0,0 @@
-%define bdbv 4.8.30
-%global selinux_variants mls strict targeted
-
-%if 0%{?_no_gui:1}
-%define _buildqt 0
-%define buildargs --with-gui=no
-%else
-%define _buildqt 1
-%if 0%{?_use_qt4}
-%define buildargs --with-qrencode --with-gui=qt4
-%else
-%define buildargs --with-qrencode --with-gui=qt5
-%endif
-%endif
-
-Name: bitcoin
-Version: 0.12.0
-Release: 2%{?dist}
-Summary: Peer to Peer Cryptographic Currency
-
-Group: Applications/System
-License: MIT
-URL: https://bitcoin.org/
-Source0: https://bitcoin.org/bin/bitcoin-core-%{version}/bitcoin-%{version}.tar.gz
-Source1: http://download.oracle.com/berkeley-db/db-%{bdbv}.NC.tar.gz
-
-Source10: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/contrib/debian/examples/bitcoin.conf
-
-#man pages
-Source20: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/doc/man/bitcoind.1
-Source21: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/doc/man/bitcoin-cli.1
-Source22: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/doc/man/bitcoin-qt.1
-
-#selinux
-Source30: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/contrib/rpm/bitcoin.te
-# Source31 - what about bitcoin-tx and bench_bitcoin ???
-Source31: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/contrib/rpm/bitcoin.fc
-Source32: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/contrib/rpm/bitcoin.if
-
-Source100: https://upload.wikimedia.org/wikipedia/commons/4/46/Bitcoin.svg
-
-%if 0%{?_use_libressl:1}
-BuildRequires: libressl-devel
-%else
-BuildRequires: openssl-devel
-%endif
-BuildRequires: boost-devel
-BuildRequires: miniupnpc-devel
-BuildRequires: autoconf automake libtool
-BuildRequires: libevent-devel
-
-
-Patch0: bitcoin-0.12.0-libressl.patch
-
-
-%description
-Bitcoin is a digital cryptographic currency that uses peer-to-peer technology to
-operate with no central authority or banks; managing transactions and the
-issuing of bitcoins is carried out collectively by the network.
-
-%if %{_buildqt}
-%package core
-Summary: Peer to Peer Cryptographic Currency
-Group: Applications/System
-Obsoletes: %{name} < %{version}-%{release}
-Provides: %{name} = %{version}-%{release}
-%if 0%{?_use_qt4}
-BuildRequires: qt-devel
-%else
-BuildRequires: qt5-qtbase-devel
-# for /usr/bin/lrelease-qt5
-BuildRequires: qt5-linguist
-%endif
-BuildRequires: protobuf-devel
-BuildRequires: qrencode-devel
-BuildRequires: %{_bindir}/desktop-file-validate
-# for icon generation from SVG
-BuildRequires: %{_bindir}/inkscape
-BuildRequires: %{_bindir}/convert
-
-%description core
-Bitcoin is a digital cryptographic currency that uses peer-to-peer technology to
-operate with no central authority or banks; managing transactions and the
-issuing of bitcoins is carried out collectively by the network.
-
-This package contains the Qt based graphical client and node. If you are looking
-to run a Bitcoin wallet, this is probably the package you want.
-%endif
-
-
-%package libs
-Summary: Bitcoin shared libraries
-Group: System Environment/Libraries
-
-%description libs
-This package provides the bitcoinconsensus shared libraries. These libraries
-may be used by third party software to provide consensus verification
-functionality.
-
-Unless you know need this package, you probably do not.
-
-%package devel
-Summary: Development files for bitcoin
-Group: Development/Libraries
-Requires: %{name}-libs = %{version}-%{release}
-
-%description devel
-This package contains the header files and static library for the
-bitcoinconsensus shared library. If you are developing or compiling software
-that wants to link against that library, then you need this package installed.
-
-Most people do not need this package installed.
-
-%package server
-Summary: The bitcoin daemon
-Group: System Environment/Daemons
-Requires: bitcoin-utils = %{version}-%{release}
-Requires: selinux-policy policycoreutils-python
-Requires(pre): shadow-utils
-Requires(post): %{_sbindir}/semodule %{_sbindir}/restorecon %{_sbindir}/fixfiles %{_sbindir}/sestatus
-Requires(postun): %{_sbindir}/semodule %{_sbindir}/restorecon %{_sbindir}/fixfiles %{_sbindir}/sestatus
-BuildRequires: systemd
-BuildRequires: checkpolicy
-BuildRequires: %{_datadir}/selinux/devel/Makefile
-
-%description server
-This package provides a stand-alone bitcoin-core daemon. For most users, this
-package is only needed if they need a full-node without the graphical client.
-
-Some third party wallet software will want this package to provide the actual
-bitcoin-core node they use to connect to the network.
-
-If you use the graphical bitcoin-core client then you almost certainly do not
-need this package.
-
-%package utils
-Summary: Bitcoin utilities
-Group: Applications/System
-
-%description utils
-This package provides several command line utilities for interacting with a
-bitcoin-core daemon.
-
-The bitcoin-cli utility allows you to communicate and control a bitcoin daemon
-over RPC, the bitcoin-tx utility allows you to create a custom transaction, and
-the bench_bitcoin utility can be used to perform some benchmarks.
-
-This package contains utilities needed by the bitcoin-server package.
-
-
-%prep
-%setup -q
-%patch0 -p1 -b .libressl
-cp -p %{SOURCE10} ./bitcoin.conf.example
-tar -zxf %{SOURCE1}
-cp -p db-%{bdbv}.NC/LICENSE ./db-%{bdbv}.NC-LICENSE
-mkdir db4 SELinux
-cp -p %{SOURCE30} %{SOURCE31} %{SOURCE32} SELinux/
-
-
-%build
-CWD=`pwd`
-cd db-%{bdbv}.NC/build_unix/
-../dist/configure --enable-cxx --disable-shared --with-pic --prefix=${CWD}/db4
-make install
-cd ../..
-
-./autogen.sh
-%configure LDFLAGS="-L${CWD}/db4/lib/" CPPFLAGS="-I${CWD}/db4/include/" --with-miniupnpc --enable-glibc-back-compat %{buildargs}
-make %{?_smp_mflags}
-
-pushd SELinux
-for selinuxvariant in %{selinux_variants}; do
- make NAME=${selinuxvariant} -f %{_datadir}/selinux/devel/Makefile
- mv bitcoin.pp bitcoin.pp.${selinuxvariant}
- make NAME=${selinuxvariant} -f %{_datadir}/selinux/devel/Makefile clean
-done
-popd
-
-
-%install
-make install DESTDIR=%{buildroot}
-
-mkdir -p -m755 %{buildroot}%{_sbindir}
-mv %{buildroot}%{_bindir}/bitcoind %{buildroot}%{_sbindir}/bitcoind
-
-# systemd stuff
-mkdir -p %{buildroot}%{_tmpfilesdir}
-cat <<EOF > %{buildroot}%{_tmpfilesdir}/bitcoin.conf
-d /run/bitcoind 0750 bitcoin bitcoin -
-EOF
-touch -a -m -t 201504280000 %{buildroot}%{_tmpfilesdir}/bitcoin.conf
-
-mkdir -p %{buildroot}%{_sysconfdir}/sysconfig
-cat <<EOF > %{buildroot}%{_sysconfdir}/sysconfig/bitcoin
-# Provide options to the bitcoin daemon here, for example
-# OPTIONS="-testnet -disable-wallet"
-
-OPTIONS=""
-
-# System service defaults.
-# Don't change these unless you know what you're doing.
-CONFIG_FILE="%{_sysconfdir}/bitcoin/bitcoin.conf"
-DATA_DIR="%{_localstatedir}/lib/bitcoin"
-PID_FILE="/run/bitcoind/bitcoind.pid"
-EOF
-touch -a -m -t 201504280000 %{buildroot}%{_sysconfdir}/sysconfig/bitcoin
-
-mkdir -p %{buildroot}%{_unitdir}
-cat <<EOF > %{buildroot}%{_unitdir}/bitcoin.service
-[Unit]
-Description=Bitcoin daemon
-After=syslog.target network.target
-
-[Service]
-Type=forking
-ExecStart=%{_sbindir}/bitcoind -daemon -conf=\${CONFIG_FILE} -datadir=\${DATA_DIR} -pid=\${PID_FILE} \$OPTIONS
-EnvironmentFile=%{_sysconfdir}/sysconfig/bitcoin
-User=bitcoin
-Group=bitcoin
-
-Restart=on-failure
-PrivateTmp=true
-TimeoutStopSec=120
-TimeoutStartSec=60
-StartLimitInterval=240
-StartLimitBurst=5
-
-[Install]
-WantedBy=multi-user.target
-EOF
-touch -a -m -t 201504280000 %{buildroot}%{_unitdir}/bitcoin.service
-#end systemd stuff
-
-mkdir %{buildroot}%{_sysconfdir}/bitcoin
-mkdir -p %{buildroot}%{_localstatedir}/lib/bitcoin
-
-#SELinux
-for selinuxvariant in %{selinux_variants}; do
- install -d %{buildroot}%{_datadir}/selinux/${selinuxvariant}
- install -p -m 644 SELinux/bitcoin.pp.${selinuxvariant} %{buildroot}%{_datadir}/selinux/${selinuxvariant}/bitcoin.pp
-done
-
-%if %{_buildqt}
-# qt icons
-install -D -p share/pixmaps/bitcoin.ico %{buildroot}%{_datadir}/pixmaps/bitcoin.ico
-install -p share/pixmaps/nsis-header.bmp %{buildroot}%{_datadir}/pixmaps/
-install -p share/pixmaps/nsis-wizard.bmp %{buildroot}%{_datadir}/pixmaps/
-install -p %{SOURCE100} %{buildroot}%{_datadir}/pixmaps/bitcoin.svg
-%{_bindir}/inkscape %{SOURCE100} --export-png=%{buildroot}%{_datadir}/pixmaps/bitcoin16.png -w16 -h16
-%{_bindir}/inkscape %{SOURCE100} --export-png=%{buildroot}%{_datadir}/pixmaps/bitcoin32.png -w32 -h32
-%{_bindir}/inkscape %{SOURCE100} --export-png=%{buildroot}%{_datadir}/pixmaps/bitcoin64.png -w64 -h64
-%{_bindir}/inkscape %{SOURCE100} --export-png=%{buildroot}%{_datadir}/pixmaps/bitcoin128.png -w128 -h128
-%{_bindir}/inkscape %{SOURCE100} --export-png=%{buildroot}%{_datadir}/pixmaps/bitcoin256.png -w256 -h256
-%{_bindir}/convert -resize 16x16 %{buildroot}%{_datadir}/pixmaps/bitcoin256.png %{buildroot}%{_datadir}/pixmaps/bitcoin16.xpm
-%{_bindir}/convert -resize 32x32 %{buildroot}%{_datadir}/pixmaps/bitcoin256.png %{buildroot}%{_datadir}/pixmaps/bitcoin32.xpm
-%{_bindir}/convert -resize 64x64 %{buildroot}%{_datadir}/pixmaps/bitcoin256.png %{buildroot}%{_datadir}/pixmaps/bitcoin64.xpm
-%{_bindir}/convert -resize 128x128 %{buildroot}%{_datadir}/pixmaps/bitcoin256.png %{buildroot}%{_datadir}/pixmaps/bitcoin128.xpm
-%{_bindir}/convert %{buildroot}%{_datadir}/pixmaps/bitcoin256.png %{buildroot}%{_datadir}/pixmaps/bitcoin256.xpm
-touch %{buildroot}%{_datadir}/pixmaps/*.png -r %{SOURCE100}
-touch %{buildroot}%{_datadir}/pixmaps/*.xpm -r %{SOURCE100}
-
-# Desktop File - change the touch timestamp if modifying
-mkdir -p %{buildroot}%{_datadir}/applications
-cat <<EOF > %{buildroot}%{_datadir}/applications/bitcoin-core.desktop
-[Desktop Entry]
-Encoding=UTF-8
-Name=Bitcoin
-Comment=Bitcoin P2P Cryptocurrency
-Comment[fr]=Bitcoin, monnaie virtuelle cryptographique pair à pair
-Comment[tr]=Bitcoin, eşten eşe kriptografik sanal para birimi
-Exec=bitcoin-qt %u
-Terminal=false
-Type=Application
-Icon=bitcoin128
-MimeType=x-scheme-handler/bitcoin;
-Categories=Office;Finance;
-EOF
-# change touch date when modifying desktop
-touch -a -m -t 201511100546 %{buildroot}%{_datadir}/applications/bitcoin-core.desktop
-%{_bindir}/desktop-file-validate %{buildroot}%{_datadir}/applications/bitcoin-core.desktop
-
-# KDE protocol - change the touch timestamp if modifying
-mkdir -p %{buildroot}%{_datadir}/kde4/services
-cat <<EOF > %{buildroot}%{_datadir}/kde4/services/bitcoin-core.protocol
-[Protocol]
-exec=bitcoin-qt '%u'
-protocol=bitcoin
-input=none
-output=none
-helper=true
-listing=
-reading=false
-writing=false
-makedir=false
-deleting=false
-EOF
-# change touch date when modifying protocol
-touch -a -m -t 201511100546 %{buildroot}%{_datadir}/kde4/services/bitcoin-core.protocol
-%endif
-
-# man pages
-install -D -p %{SOURCE20} %{buildroot}%{_mandir}/man1/bitcoind.1
-install -p %{SOURCE21} %{buildroot}%{_mandir}/man1/bitcoin-cli.1
-%if %{_buildqt}
-install -p %{SOURCE22} %{buildroot}%{_mandir}/man1/bitcoin-qt.1
-%endif
-
-# nuke these, we do extensive testing of binaries in %%check before packaging
-rm -f %{buildroot}%{_bindir}/test_*
-
-%check
-make check
-srcdir=src test/bitcoin-util-test.py
-test/functional/test_runner.py --extended
-
-%post libs -p /sbin/ldconfig
-
-%postun libs -p /sbin/ldconfig
-
-%pre server
-getent group bitcoin >/dev/null || groupadd -r bitcoin
-getent passwd bitcoin >/dev/null ||
- useradd -r -g bitcoin -d /var/lib/bitcoin -s /sbin/nologin \
- -c "Bitcoin wallet server" bitcoin
-exit 0
-
-%post server
-%systemd_post bitcoin.service
-# SELinux
-if [ `%{_sbindir}/sestatus |grep -c "disabled"` -eq 0 ]; then
-for selinuxvariant in %{selinux_variants}; do
- %{_sbindir}/semodule -s ${selinuxvariant} -i %{_datadir}/selinux/${selinuxvariant}/bitcoin.pp &> /dev/null || :
-done
-%{_sbindir}/semanage port -a -t bitcoin_port_t -p tcp 8332
-%{_sbindir}/semanage port -a -t bitcoin_port_t -p tcp 8333
-%{_sbindir}/semanage port -a -t bitcoin_port_t -p tcp 18332
-%{_sbindir}/semanage port -a -t bitcoin_port_t -p tcp 18333
-%{_sbindir}/semanage port -a -t bitcoin_port_t -p tcp 18443
-%{_sbindir}/semanage port -a -t bitcoin_port_t -p tcp 18444
-%{_sbindir}/fixfiles -R bitcoin-server restore &> /dev/null || :
-%{_sbindir}/restorecon -R %{_localstatedir}/lib/bitcoin || :
-fi
-
-%posttrans server
-%{_bindir}/systemd-tmpfiles --create
-
-%preun server
-%systemd_preun bitcoin.service
-
-%postun server
-%systemd_postun bitcoin.service
-# SELinux
-if [ $1 -eq 0 ]; then
- if [ `%{_sbindir}/sestatus |grep -c "disabled"` -eq 0 ]; then
- %{_sbindir}/semanage port -d -p tcp 8332
- %{_sbindir}/semanage port -d -p tcp 8333
- %{_sbindir}/semanage port -d -p tcp 18332
- %{_sbindir}/semanage port -d -p tcp 18333
- %{_sbindir}/semanage port -d -p tcp 18443
- %{_sbindir}/semanage port -d -p tcp 18444
- for selinuxvariant in %{selinux_variants}; do
- %{_sbindir}/semodule -s ${selinuxvariant} -r bitcoin &> /dev/null || :
- done
- %{_sbindir}/fixfiles -R bitcoin-server restore &> /dev/null || :
- [ -d %{_localstatedir}/lib/bitcoin ] && \
- %{_sbindir}/restorecon -R %{_localstatedir}/lib/bitcoin &> /dev/null || :
- fi
-fi
-
-%clean
-rm -rf %{buildroot}
-
-%if %{_buildqt}
-%files core
-%defattr(-,root,root,-)
-%license COPYING db-%{bdbv}.NC-LICENSE
-%doc COPYING bitcoin.conf.example doc/README.md doc/bips.md doc/files.md doc/multiwallet-qt.md doc/reduce-traffic.md doc/release-notes.md doc/tor.md
-%attr(0755,root,root) %{_bindir}/bitcoin-qt
-%attr(0644,root,root) %{_datadir}/applications/bitcoin-core.desktop
-%attr(0644,root,root) %{_datadir}/kde4/services/bitcoin-core.protocol
-%attr(0644,root,root) %{_datadir}/pixmaps/*.ico
-%attr(0644,root,root) %{_datadir}/pixmaps/*.bmp
-%attr(0644,root,root) %{_datadir}/pixmaps/*.svg
-%attr(0644,root,root) %{_datadir}/pixmaps/*.png
-%attr(0644,root,root) %{_datadir}/pixmaps/*.xpm
-%attr(0644,root,root) %{_mandir}/man1/bitcoin-qt.1*
-%endif
-
-%files libs
-%defattr(-,root,root,-)
-%license COPYING
-%doc COPYING doc/README.md doc/shared-libraries.md
-%{_libdir}/lib*.so.*
-
-%files devel
-%defattr(-,root,root,-)
-%license COPYING
-%doc COPYING doc/README.md doc/developer-notes.md doc/shared-libraries.md
-%attr(0644,root,root) %{_includedir}/*.h
-%{_libdir}/*.so
-%{_libdir}/*.a
-%{_libdir}/*.la
-%attr(0644,root,root) %{_libdir}/pkgconfig/*.pc
-
-%files server
-%defattr(-,root,root,-)
-%license COPYING db-%{bdbv}.NC-LICENSE
-%doc COPYING bitcoin.conf.example doc/README.md doc/REST-interface.md doc/bips.md doc/dnsseed-policy.md doc/files.md doc/reduce-traffic.md doc/release-notes.md doc/tor.md
-%attr(0755,root,root) %{_sbindir}/bitcoind
-%attr(0644,root,root) %{_tmpfilesdir}/bitcoin.conf
-%attr(0644,root,root) %{_unitdir}/bitcoin.service
-%dir %attr(0750,bitcoin,bitcoin) %{_sysconfdir}/bitcoin
-%dir %attr(0750,bitcoin,bitcoin) %{_localstatedir}/lib/bitcoin
-%config(noreplace) %attr(0600,root,root) %{_sysconfdir}/sysconfig/bitcoin
-%attr(0644,root,root) %{_datadir}/selinux/*/*.pp
-%attr(0644,root,root) %{_mandir}/man1/bitcoind.1*
-
-%files utils
-%defattr(-,root,root,-)
-%license COPYING
-%doc COPYING bitcoin.conf.example doc/README.md
-%attr(0755,root,root) %{_bindir}/bitcoin-cli
-%attr(0755,root,root) %{_bindir}/bitcoin-tx
-%attr(0755,root,root) %{_bindir}/bench_bitcoin
-%attr(0644,root,root) %{_mandir}/man1/bitcoin-cli.1*
-
-
-
-%changelog
-* Fri Feb 26 2016 Alice Wonder <buildmaster@librelamp.com> - 0.12.0-2
-- Rename Qt package from bitcoin to bitcoin-core
-- Make building of the Qt package optional
-- When building the Qt package, default to Qt5 but allow building
-- against Qt4
-- Only run SELinux stuff in post scripts if it is not set to disabled
-
-* Wed Feb 24 2016 Alice Wonder <buildmaster@librelamp.com> - 0.12.0-1
-- Initial spec file for 0.12.0 release
-
-# This spec file is written from scratch but a lot of the packaging decisions are directly
-# based upon the 0.11.2 package spec file from https://www.ringingliberty.com/bitcoin/
diff --git a/contrib/rpm/bitcoin.te b/contrib/rpm/bitcoin.te
deleted file mode 100644
index d6231c591a..0000000000
--- a/contrib/rpm/bitcoin.te
+++ /dev/null
@@ -1,81 +0,0 @@
-policy_module(bitcoin, 1.100.1)
-
-########################################
-#
-# Declarations
-#
-
-type bitcoin_t;
-type bitcoin_exec_t;
-init_daemon_domain(bitcoin_t, bitcoin_exec_t)
-
-permissive bitcoin_t;
-
-type bitcoin_initrc_exec_t;
-init_script_file(bitcoin_initrc_exec_t)
-
-type bitcoin_conf_t;
-files_type(bitcoin_conf_t)
-
-type bitcoin_var_lib_t;
-files_type(bitcoin_var_lib_t)
-
-type bitcoin_var_run_t;
-files_type(bitcoin_var_run_t)
-
-type bitcoin_port_t;
-corenet_port(bitcoin_port_t)
-
-########################################
-#
-# bitcoin local policy
-#
-allow bitcoin_t self:process { fork };
-
-allow bitcoin_t self:fifo_file rw_fifo_file_perms;
-allow bitcoin_t self:unix_stream_socket create_stream_socket_perms;
-
-manage_dirs_pattern(bitcoin_t, bitcoin_conf_t, bitcoin_conf_t)
-manage_files_pattern(bitcoin_t, bitcoin_conf_t, bitcoin_conf_t)
-
-manage_dirs_pattern(bitcoin_t, bitcoin_var_lib_t, bitcoin_var_lib_t)
-manage_files_pattern(bitcoin_t, bitcoin_var_lib_t, bitcoin_var_lib_t)
-files_var_lib_filetrans(bitcoin_t, bitcoin_var_lib_t, { dir file })
-
-manage_dirs_pattern(bitcoin_t, bitcoin_var_run_t, bitcoin_var_run_t)
-manage_files_pattern(bitcoin_t, bitcoin_var_run_t, bitcoin_var_run_t)
-
-sysnet_dns_name_resolve(bitcoin_t)
-corenet_all_recvfrom_unlabeled(bitcoin_t)
-
-allow bitcoin_t self:tcp_socket create_stream_socket_perms;
-corenet_tcp_sendrecv_generic_if(bitcoin_t)
-corenet_tcp_sendrecv_generic_node(bitcoin_t)
-corenet_tcp_sendrecv_all_ports(bitcoin_t)
-corenet_tcp_bind_generic_node(bitcoin_t)
-
-gen_require(`
- type bitcoin_port_t;
-')
-allow bitcoin_t bitcoin_port_t:tcp_socket name_bind;
-
-gen_require(`
- type bitcoin_port_t;
-')
-allow bitcoin_t bitcoin_port_t:tcp_socket name_connect;
-
-domain_use_interactive_fds(bitcoin_t)
-
-files_read_etc_files(bitcoin_t)
-
-miscfiles_read_localization(bitcoin_t)
-
-sysnet_dns_name_resolve(bitcoin_t)
-
-allow bitcoin_t bitcoin_exec_t:file execute_no_trans;
-allow bitcoin_t self:process setsched;
-corecmd_exec_ls(bitcoin_t)
-corenet_tcp_connect_http_port(bitcoin_t)
-dev_read_urand(bitcoin_t)
-fs_getattr_xattr_fs(bitcoin_t)
-kernel_read_system_state(bitcoin_t)
diff --git a/doc/bips.md b/doc/bips.md
index 272cf4de29..eb29b036cc 100644
--- a/doc/bips.md
+++ b/doc/bips.md
@@ -1,4 +1,4 @@
-BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.16.0**):
+BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.17.0**):
* [`BIP 9`](https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki): The changes allowing multiple soft-forks to be deployed in parallel have been implemented since **v0.12.1** ([PR #7575](https://github.com/bitcoin/bitcoin/pull/7575))
* [`BIP 11`](https://github.com/bitcoin/bips/blob/master/bip-0011.mediawiki): Multisig outputs are standard since **v0.6.0** ([PR #669](https://github.com/bitcoin/bitcoin/pull/669)).
@@ -35,4 +35,5 @@ BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.16.0**):
* [`BIP 152`](https://github.com/bitcoin/bips/blob/master/bip-0152.mediawiki): Compact block transfer and related optimizations are used as of **v0.13.0** ([PR 8068](https://github.com/bitcoin/bitcoin/pull/8068)).
* [`BIP 159`](https://github.com/bitcoin/bips/blob/master/bip-0159.mediawiki): NODE_NETWORK_LIMITED service bit [signaling only] is supported as of **v0.16.0** ([PR 11740](https://github.com/bitcoin/bitcoin/pull/11740)).
* [`BIP 173`](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki): Bech32 addresses for native Segregated Witness outputs are supported as of **v0.16.0** ([PR 11167](https://github.com/bitcoin/bitcoin/pull/11167)).
+* [`BIP 174`](https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki): RPCs to operate on Partially Signed Bitcoin Transactions (PSBT) are present as of **v0.17.0** ([PR 13557](https://github.com/bitcoin/bitcoin/pull/13557)).
* [`BIP 176`](https://github.com/bitcoin/bips/blob/master/bip-0176.mediawiki): Bits Denomination [QT only] is supported as of **v0.16.0** ([PR 12035](https://github.com/bitcoin/bitcoin/pull/12035)).
diff --git a/doc/init.md b/doc/init.md
index d04f7d186a..239b74e4e1 100644
--- a/doc/init.md
+++ b/doc/init.md
@@ -44,7 +44,7 @@ This allows for running bitcoind without having to do any manual configuration.
relative to the data directory. `wallet` *only* supports relative paths.
For an example configuration file that describes the configuration settings,
-see `contrib/debian/examples/bitcoin.conf`.
+see `share/examples/bitcoin.conf`.
Paths
---------------------------------
diff --git a/contrib/debian/examples/bitcoin.conf b/share/examples/bitcoin.conf
index 4dd73162a2..4dd73162a2 100644
--- a/contrib/debian/examples/bitcoin.conf
+++ b/share/examples/bitcoin.conf
diff --git a/src/Makefile.am b/src/Makefile.am
index 60ecf07a59..d1693fa85c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -158,6 +158,7 @@ BITCOIN_CORE_H = \
rpc/register.h \
rpc/util.h \
scheduler.h \
+ script/descriptor.h \
script/ismine.h \
script/sigcache.h \
script/sign.h \
@@ -387,6 +388,7 @@ libbitcoin_common_a_SOURCES = \
policy/feerate.cpp \
protocol.cpp \
scheduler.cpp \
+ script/descriptor.cpp \
script/ismine.cpp \
script/sign.cpp \
script/standard.cpp \
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index 02f2063504..6f401636f5 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -47,6 +47,7 @@ BITCOIN_TESTS =\
test/crypto_tests.cpp \
test/cuckoocache_tests.cpp \
test/denialofservice_tests.cpp \
+ test/descriptor_tests.cpp \
test/getarg_tests.cpp \
test/hash_tests.cpp \
test/key_io_tests.cpp \
diff --git a/src/bench/coin_selection.cpp b/src/bench/coin_selection.cpp
index 7510d53c88..20013d702b 100644
--- a/src/bench/coin_selection.cpp
+++ b/src/bench/coin_selection.cpp
@@ -21,7 +21,7 @@ static void addCoin(const CAmount& nValue, const CWallet& wallet, std::vector<Ou
int nAge = 6 * 24;
COutput output(wtx, nInput, nAge, true /* spendable */, true /* solvable */, true /* safe */);
- groups.emplace_back(output.GetInputCoin(), 0, false, 0, 0);
+ groups.emplace_back(output.GetInputCoin(), 6, false, 0, 0);
}
// Simple benchmark for wallet coin selection. Note that it maybe be necessary
diff --git a/src/bench/mempool_eviction.cpp b/src/bench/mempool_eviction.cpp
index 4c947a519f..d37291b900 100644
--- a/src/bench/mempool_eviction.cpp
+++ b/src/bench/mempool_eviction.cpp
@@ -9,7 +9,7 @@
#include <list>
#include <vector>
-static void AddTx(const CTransactionRef& tx, const CAmount& nFee, CTxMemPool& pool)
+static void AddTx(const CTransactionRef& tx, const CAmount& nFee, CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(pool.cs)
{
int64_t nTime = 0;
unsigned int nHeight = 1;
@@ -108,6 +108,7 @@ static void MempoolEviction(benchmark::State& state)
tx7.vout[1].nValue = 10 * COIN;
CTxMemPool pool;
+ LOCK(pool.cs);
// Create transaction references outside the "hot loop"
const CTransactionRef tx1_r{MakeTransactionRef(tx1)};
const CTransactionRef tx2_r{MakeTransactionRef(tx2)};
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
index 5c711c0773..4d010c0d14 100644
--- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -96,7 +96,7 @@ static bool AppInit(int argc, char* argv[])
fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", gArgs.GetArg("-datadir", "").c_str());
return false;
}
- if (!gArgs.ReadConfigFiles(error)) {
+ if (!gArgs.ReadConfigFiles(error, true)) {
fprintf(stderr, "Error reading configuration file: %s\n", error.c_str());
return false;
}
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index 71762158f0..b517717c97 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -102,10 +102,10 @@ public:
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1510704000; // November 15th, 2017.
// The best chain should have at least this much work.
- consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000000f91c579d57cad4bc5278cc");
+ consensus.nMinimumChainWork = uint256S("0x0000000000000000000000000000000000000000028822fef1c230963535a90d");
// By default assume that the signatures in ancestors of this block are valid.
- consensus.defaultAssumeValid = uint256S("0x0000000000000000005214481d2d96f898e3d5416e43359c145944a909d242e0"); //506067
+ consensus.defaultAssumeValid = uint256S("0x0000000000000000002e63058c023a9a1de233554f28c7b21380b6c9003f36a8"); //534292
/**
* The message start string is designed to be unlikely to occur in normal data.
@@ -170,11 +170,10 @@ public:
};
chainTxData = ChainTxData{
- // Data as of block 0000000000000000002d6cca6761c99b3c2e936f9a0e304b7c7651a993f461de (height 506081).
- 1516903077, // * UNIX timestamp of last known number of transactions
- 295363220, // * total number of transactions between genesis and that timestamp
- // (the tx=... number in the ChainStateFlushed debug.log lines)
- 3.5 // * estimated number of transactions per second after that timestamp
+ // Data from rpc: getchaintxstats 4096 0000000000000000002e63058c023a9a1de233554f28c7b21380b6c9003f36a8
+ /* nTime */ 1532884444,
+ /* nTxCount */ 331282217,
+ /* dTxRate */ 2.4
};
/* disable fallback fee on mainnet */
@@ -217,10 +216,10 @@ public:
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1493596800; // May 1st 2017
// The best chain should have at least this much work.
- consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000002830dab7f76dbb7d63");
+ consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000007dbe94253893cbd463");
// By default assume that the signatures in ancestors of this block are valid.
- consensus.defaultAssumeValid = uint256S("0x0000000002e9e7b00e1f6dc5123a04aad68dd0f0968d8c7aa45f6640795c37b1"); //1135275
+ consensus.defaultAssumeValid = uint256S("0x0000000000000037a8cd3e06cd5edbfe9dd1dbcc5dacab279376ef7cfc2b4c75"); //1354312
pchMessageStart[0] = 0x0b;
pchMessageStart[1] = 0x11;
@@ -264,10 +263,10 @@ public:
};
chainTxData = ChainTxData{
- // Data as of block 000000000000033cfa3c975eb83ecf2bb4aaedf68e6d279f6ed2b427c64caff9 (height 1260526)
- 1516903490,
- 17082348,
- 0.09
+ // Data from rpc: getchaintxstats 4096 0000000000000037a8cd3e06cd5edbfe9dd1dbcc5dacab279376ef7cfc2b4c75
+ /* nTime */ 1531929919,
+ /* nTxCount */ 19438708,
+ /* dTxRate */ 0.626
};
/* enable fallback fee on testnet */
diff --git a/src/chainparams.h b/src/chainparams.h
index dd029b9d5b..344cbb1a8a 100644
--- a/src/chainparams.h
+++ b/src/chainparams.h
@@ -32,9 +32,9 @@ struct CCheckpointData {
* See also: CChainParams::TxData, GuessVerificationProgress.
*/
struct ChainTxData {
- int64_t nTime;
- int64_t nTxCount;
- double dTxRate;
+ int64_t nTime; //!< UNIX timestamp of last known number of transactions
+ int64_t nTxCount; //!< total number of transactions between genesis and that timestamp
+ double dTxRate; //!< estimated number of transactions per second after that timestamp
};
/**
diff --git a/src/init.cpp b/src/init.cpp
index 18402ef5d7..21445929dc 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -382,7 +382,7 @@ void SetupServerArgs()
#endif
gArgs.AddArg("-prune=<n>", strprintf("Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. "
"Warning: Reverting this setting requires re-downloading the entire blockchain. "
- "(default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, >%u = automatically prune block files to stay under the specified target size in MiB)", MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024), false, OptionsCategory::OPTIONS);
+ "(default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, >=%u = automatically prune block files to stay under the specified target size in MiB)", MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024), false, OptionsCategory::OPTIONS);
gArgs.AddArg("-reindex", "Rebuild chain state and block index from the blk*.dat files on disk", false, OptionsCategory::OPTIONS);
gArgs.AddArg("-reindex-chainstate", "Rebuild chain state from the currently indexed blocks", false, OptionsCategory::OPTIONS);
#ifndef WIN32
diff --git a/src/interfaces/node.cpp b/src/interfaces/node.cpp
index db371d104e..106dd38f60 100644
--- a/src/interfaces/node.cpp
+++ b/src/interfaces/node.cpp
@@ -53,7 +53,7 @@ class NodeImpl : public Node
{
return gArgs.ParseParameters(argc, argv, error);
}
- bool readConfigFiles(std::string& error) override { return gArgs.ReadConfigFiles(error); }
+ bool readConfigFiles(std::string& error) override { return gArgs.ReadConfigFiles(error, true); }
bool softSetArg(const std::string& arg, const std::string& value) override { return gArgs.SoftSetArg(arg, value); }
bool softSetBoolArg(const std::string& arg, bool value) override { return gArgs.SoftSetBoolArg(arg, value); }
void selectParams(const std::string& network) override { SelectParams(network); }
diff --git a/src/net.cpp b/src/net.cpp
index 0ebfefa757..5be91fd4f3 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -1798,7 +1798,6 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
CAddress addrConnect;
// Only connect out to one peer per network group (/16 for IPv4).
- // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
int nOutbound = 0;
std::set<std::vector<unsigned char> > setConnected;
{
diff --git a/src/netaddress.cpp b/src/netaddress.cpp
index 5ccbabd03d..193582d14e 100644
--- a/src/netaddress.cpp
+++ b/src/netaddress.cpp
@@ -300,6 +300,9 @@ bool CNetAddr::GetInAddr(struct in_addr* pipv4Addr) const
bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const
{
+ if (!IsIPv6()) {
+ return false;
+ }
memcpy(pipv6Addr, ip, 16);
return true;
}
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 012e3e3ac1..46dec4ca6e 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -20,6 +20,7 @@
#include <policy/policy.h>
#include <primitives/transaction.h>
#include <rpc/server.h>
+#include <script/descriptor.h>
#include <streams.h>
#include <sync.h>
#include <txdb.h>
@@ -1984,67 +1985,38 @@ public:
}
};
-static const char *g_default_scantxoutset_script_types[] = { "P2PKH", "P2SH_P2WPKH", "P2WPKH" };
-
-enum class OutputScriptType {
- UNKNOWN,
- P2PK,
- P2PKH,
- P2SH_P2WPKH,
- P2WPKH
-};
-
-static inline OutputScriptType GetOutputScriptTypeFromString(const std::string& outputtype)
-{
- if (outputtype == "P2PK") return OutputScriptType::P2PK;
- else if (outputtype == "P2PKH") return OutputScriptType::P2PKH;
- else if (outputtype == "P2SH_P2WPKH") return OutputScriptType::P2SH_P2WPKH;
- else if (outputtype == "P2WPKH") return OutputScriptType::P2WPKH;
- else return OutputScriptType::UNKNOWN;
-}
-
-CTxDestination GetDestinationForKey(const CPubKey& key, OutputScriptType type)
-{
- switch (type) {
- case OutputScriptType::P2PKH: return key.GetID();
- case OutputScriptType::P2SH_P2WPKH:
- case OutputScriptType::P2WPKH: {
- if (!key.IsCompressed()) return key.GetID();
- CTxDestination witdest = WitnessV0KeyHash(key.GetID());
- if (type == OutputScriptType::P2SH_P2WPKH) {
- CScript witprog = GetScriptForDestination(witdest);
- return CScriptID(witprog);
- } else {
- return witdest;
- }
- }
- default: assert(false);
- }
-}
-
UniValue scantxoutset(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
"scantxoutset <action> ( <scanobjects> )\n"
- "\nScans the unspent transaction output set for possible entries that matches common scripts of given public keys.\n"
- "Using addresses as scanobjects will _not_ detect unspent P2PK txouts\n"
+ "\nEXPERIMENTAL warning: this call may be removed or changed in future releases.\n"
+ "\nScans the unspent transaction output set for entries that match certain output descriptors.\n"
+ "Examples of output descriptors are:\n"
+ " addr(<address>) Outputs whose scriptPubKey corresponds to the specified address (does not include P2PK)\n"
+ " raw(<hex script>) Outputs whose scriptPubKey equals the specified hex scripts\n"
+ " combo(<pubkey>) P2PK, P2PKH, P2WPKH, and P2SH-P2WPKH outputs for the given pubkey\n"
+ " pkh(<pubkey>) P2PKH outputs for the given pubkey\n"
+ " sh(multi(<n>,<pubkey>,<pubkey>,...)) P2SH-multisig outputs for the given threshold and pubkeys\n"
+ "\nIn the above, <pubkey> either refers to a fixed public key in hexadecimal notation, or to an xpub/xprv optionally followed by one\n"
+ "or more path elements separated by \"/\", and optionally ending in \"/*\" (unhardened), or \"/*'\" or \"/*h\" (hardened) to specify all\n"
+ "unhardened or hardened child keys.\n"
+ "In the latter case, a range needs to be specified by below if different from 1000.\n"
+ "For more information on output descriptors, see the documentation at TODO\n"
"\nArguments:\n"
"1. \"action\" (string, required) The action to execute\n"
" \"start\" for starting a scan\n"
" \"abort\" for aborting the current scan (returns true when abort was successful)\n"
" \"status\" for progress report (in %) of the current scan\n"
- "2. \"scanobjects\" (array, optional) Array of scan objects (only one object type per scan object allowed)\n"
- " [\n"
- " { \"address\" : \"<address>\" }, (string, optional) Bitcoin address\n"
- " { \"script\" : \"<scriptPubKey>\" }, (string, optional) HEX encoded script (scriptPubKey)\n"
- " { \"pubkey\" : (object, optional) Public key\n"
- " {\n"
- " \"pubkey\" : \"<pubkey\">, (string, required) HEX encoded public key\n"
- " \"script_types\" : [ ... ], (array, optional) Array of script-types to derive from the pubkey (possible values: \"P2PK\", \"P2PKH\", \"P2SH-P2WPKH\", \"P2WPKH\")\n"
- " }\n"
+ "2. \"scanobjects\" (array, required) Array of scan objects\n"
+ " [ Every scan object is either a string descriptor or an object:\n"
+ " \"descriptor\", (string, optional) An output descriptor\n"
+ " { (object, optional) An object with output descriptor and metadata\n"
+ " \"desc\": \"descriptor\", (string, required) An output descriptor\n"
+ " \"range\": n, (numeric, optional) Up to what child index HD chains should be explored (default: 1000)\n"
" },\n"
- " ]\n"
+ " ...\n"
+ " ]\n"
"\nResult:\n"
"{\n"
" \"unspents\": [\n"
@@ -2090,79 +2062,35 @@ UniValue scantxoutset(const JSONRPCRequest& request)
// loop through the scan objects
for (const UniValue& scanobject : request.params[1].get_array().getValues()) {
- if (!scanobject.isObject()) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid scan object");
- }
- UniValue address_uni = find_value(scanobject, "address");
- UniValue pubkey_uni = find_value(scanobject, "pubkey");
- UniValue script_uni = find_value(scanobject, "script");
-
- // make sure only one object type is present
- if (1 != !address_uni.isNull() + !pubkey_uni.isNull() + !script_uni.isNull()) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Only one object type is allowed per scan object");
- } else if (!address_uni.isNull() && !address_uni.isStr()) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Scanobject \"address\" must contain a single string as value");
- } else if (!pubkey_uni.isNull() && !pubkey_uni.isObject()) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Scanobject \"pubkey\" must contain an object as value");
- } else if (!script_uni.isNull() && !script_uni.isStr()) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Scanobject \"script\" must contain a single string as value");
- } else if (address_uni.isStr()) {
- // type: address
- // decode destination and derive the scriptPubKey
- // add the script to the scan containers
- CTxDestination dest = DecodeDestination(address_uni.get_str());
- if (!IsValidDestination(dest)) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
- }
- CScript script = GetScriptForDestination(dest);
- assert(!script.empty());
- needles.insert(script);
- } else if (pubkey_uni.isObject()) {
- // type: pubkey
- // derive script(s) according to the script_type parameter
- UniValue script_types_uni = find_value(pubkey_uni, "script_types");
- UniValue pubkeydata_uni = find_value(pubkey_uni, "pubkey");
-
- // check the script types and use the default if not provided
- if (!script_types_uni.isNull() && !script_types_uni.isArray()) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "script_types must be an array");
- } else if (script_types_uni.isNull()) {
- // use the default script types
- script_types_uni = UniValue(UniValue::VARR);
- for (const char *t : g_default_scantxoutset_script_types) {
- script_types_uni.push_back(t);
- }
- }
-
- // check the acctual pubkey
- if (!pubkeydata_uni.isStr() || !IsHex(pubkeydata_uni.get_str())) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Public key must be hex encoded");
- }
- CPubKey pubkey(ParseHexV(pubkeydata_uni, "pubkey"));
- if (!pubkey.IsFullyValid()) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid public key");
+ std::string desc_str;
+ int range = 1000;
+ if (scanobject.isStr()) {
+ desc_str = scanobject.get_str();
+ } else if (scanobject.isObject()) {
+ UniValue desc_uni = find_value(scanobject, "desc");
+ if (desc_uni.isNull()) throw JSONRPCError(RPC_INVALID_PARAMETER, "Descriptor needs to be provided in scan object");
+ desc_str = desc_uni.get_str();
+ UniValue range_uni = find_value(scanobject, "range");
+ if (!range_uni.isNull()) {
+ range = range_uni.get_int();
+ if (range < 0 || range > 1000000) throw JSONRPCError(RPC_INVALID_PARAMETER, "range out of range");
}
+ } else {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Scan object needs to be either a string or an object");
+ }
- // loop through the script types and derive the script
- for (const UniValue& script_type_uni : script_types_uni.get_array().getValues()) {
- OutputScriptType script_type = GetOutputScriptTypeFromString(script_type_uni.get_str());
- if (script_type == OutputScriptType::UNKNOWN) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid script type");
- CScript script;
- if (script_type == OutputScriptType::P2PK) {
- // support legacy P2PK scripts
- script << ToByteVector(pubkey) << OP_CHECKSIG;
- } else {
- script = GetScriptForDestination(GetDestinationForKey(pubkey, script_type));
- }
- assert(!script.empty());
- needles.insert(script);
+ FlatSigningProvider provider;
+ auto desc = Parse(desc_str, provider);
+ if (!desc) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Invalid descriptor '%s'", desc_str));
+ }
+ if (!desc->IsRange()) range = 0;
+ for (int i = 0; i <= range; ++i) {
+ std::vector<CScript> scripts;
+ if (!desc->Expand(i, provider, scripts, provider)) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Cannot derive script without private keys: '%s'", desc_str));
}
- } else if (script_uni.isStr()) {
- // type: script
- // check and add the script to the scan containers (needles array)
- CScript script(ParseHexV(script_uni, "script"));
- // TODO: check script: max length, has OP, is unspenable etc.
- needles.insert(script);
+ needles.insert(scripts.begin(), scripts.end());
}
}
diff --git a/src/scheduler.h b/src/scheduler.h
index 7169dceee5..66fd44d179 100644
--- a/src/scheduler.h
+++ b/src/scheduler.h
@@ -86,9 +86,13 @@ private:
/**
* Class used by CScheduler clients which may schedule multiple jobs
- * which are required to be run serially. Does not require such jobs
- * to be executed on the same thread, but no two jobs will be executed
- * at the same time.
+ * which are required to be run serially. Jobs may not be run on the
+ * same thread, but no two jobs will be executed
+ * at the same time and memory will be release-acquire consistent
+ * (the scheduler will internally do an acquire before invoking a callback
+ * as well as a release at the end). In practice this means that a callback
+ * B() will be able to observe all of the effects of callback A() which executed
+ * before it.
*/
class SingleThreadedSchedulerClient {
private:
@@ -103,6 +107,13 @@ private:
public:
explicit SingleThreadedSchedulerClient(CScheduler *pschedulerIn) : m_pscheduler(pschedulerIn) {}
+
+ /**
+ * Add a callback to be executed. Callbacks are executed serially
+ * and memory is release-acquire consistent between callback executions.
+ * Practially, this means that callbacks can behave as if they are executed
+ * in order by a single thread.
+ */
void AddToProcessQueue(std::function<void (void)> func);
// Processes all remaining queue members on the calling thread, blocking until queue is empty
diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp
new file mode 100644
index 0000000000..f366b99ec3
--- /dev/null
+++ b/src/script/descriptor.cpp
@@ -0,0 +1,566 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <script/descriptor.h>
+
+#include <key_io.h>
+#include <pubkey.h>
+#include <script/script.h>
+#include <script/standard.h>
+
+#include <span.h>
+#include <util.h>
+#include <utilstrencodings.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace {
+
+////////////////////////////////////////////////////////////////////////////
+// Internal representation //
+////////////////////////////////////////////////////////////////////////////
+
+typedef std::vector<uint32_t> KeyPath;
+
+std::string FormatKeyPath(const KeyPath& path)
+{
+ std::string ret;
+ for (auto i : path) {
+ ret += strprintf("/%i", (i << 1) >> 1);
+ if (i >> 31) ret += '\'';
+ }
+ return ret;
+}
+
+/** Interface for public key objects in descriptors. */
+struct PubkeyProvider
+{
+ virtual ~PubkeyProvider() = default;
+
+ /** Derive a public key. */
+ virtual bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& out) const = 0;
+
+ /** Whether this represent multiple public keys at different positions. */
+ virtual bool IsRange() const = 0;
+
+ /** Get the size of the generated public key(s) in bytes (33 or 65). */
+ virtual size_t GetSize() const = 0;
+
+ /** Get the descriptor string form. */
+ virtual std::string ToString() const = 0;
+
+ /** Get the descriptor string form including private data (if available in arg). */
+ virtual bool ToPrivateString(const SigningProvider& arg, std::string& out) const = 0;
+};
+
+/** An object representing a parsed constant public key in a descriptor. */
+class ConstPubkeyProvider final : public PubkeyProvider
+{
+ CPubKey m_pubkey;
+
+public:
+ ConstPubkeyProvider(const CPubKey& pubkey) : m_pubkey(pubkey) {}
+ bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& out) const override
+ {
+ out = m_pubkey;
+ return true;
+ }
+ bool IsRange() const override { return false; }
+ size_t GetSize() const override { return m_pubkey.size(); }
+ std::string ToString() const override { return HexStr(m_pubkey.begin(), m_pubkey.end()); }
+ bool ToPrivateString(const SigningProvider& arg, std::string& ret) const override
+ {
+ CKey key;
+ if (!arg.GetKey(m_pubkey.GetID(), key)) return false;
+ ret = EncodeSecret(key);
+ return true;
+ }
+};
+
+enum class DeriveType {
+ NO,
+ UNHARDENED,
+ HARDENED,
+};
+
+/** An object representing a parsed extended public key in a descriptor. */
+class BIP32PubkeyProvider final : public PubkeyProvider
+{
+ CExtPubKey m_extkey;
+ KeyPath m_path;
+ DeriveType m_derive;
+
+ bool GetExtKey(const SigningProvider& arg, CExtKey& ret) const
+ {
+ CKey key;
+ if (!arg.GetKey(m_extkey.pubkey.GetID(), key)) return false;
+ ret.nDepth = m_extkey.nDepth;
+ std::copy(m_extkey.vchFingerprint, m_extkey.vchFingerprint + 4, ret.vchFingerprint);
+ ret.nChild = m_extkey.nChild;
+ ret.chaincode = m_extkey.chaincode;
+ ret.key = key;
+ return true;
+ }
+
+ bool IsHardened() const
+ {
+ if (m_derive == DeriveType::HARDENED) return true;
+ for (auto entry : m_path) {
+ if (entry >> 31) return true;
+ }
+ return false;
+ }
+
+public:
+ BIP32PubkeyProvider(const CExtPubKey& extkey, KeyPath path, DeriveType derive) : m_extkey(extkey), m_path(std::move(path)), m_derive(derive) {}
+ bool IsRange() const override { return m_derive != DeriveType::NO; }
+ size_t GetSize() const override { return 33; }
+ bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& out) const override
+ {
+ if (IsHardened()) {
+ CExtKey key;
+ if (!GetExtKey(arg, key)) return false;
+ for (auto entry : m_path) {
+ key.Derive(key, entry);
+ }
+ if (m_derive == DeriveType::UNHARDENED) key.Derive(key, pos);
+ if (m_derive == DeriveType::HARDENED) key.Derive(key, pos | 0x80000000UL);
+ out = key.Neuter().pubkey;
+ } else {
+ // TODO: optimize by caching
+ CExtPubKey key = m_extkey;
+ for (auto entry : m_path) {
+ key.Derive(key, entry);
+ }
+ if (m_derive == DeriveType::UNHARDENED) key.Derive(key, pos);
+ assert(m_derive != DeriveType::HARDENED);
+ out = key.pubkey;
+ }
+ return true;
+ }
+ std::string ToString() const override
+ {
+ std::string ret = EncodeExtPubKey(m_extkey) + FormatKeyPath(m_path);
+ if (IsRange()) {
+ ret += "/*";
+ if (m_derive == DeriveType::HARDENED) ret += '\'';
+ }
+ return ret;
+ }
+ bool ToPrivateString(const SigningProvider& arg, std::string& out) const override
+ {
+ CExtKey key;
+ if (!GetExtKey(arg, key)) return false;
+ out = EncodeExtKey(key) + FormatKeyPath(m_path);
+ if (IsRange()) {
+ out += "/*";
+ if (m_derive == DeriveType::HARDENED) out += '\'';
+ }
+ return true;
+ }
+};
+
+/** A parsed addr(A) descriptor. */
+class AddressDescriptor final : public Descriptor
+{
+ CTxDestination m_destination;
+
+public:
+ AddressDescriptor(CTxDestination destination) : m_destination(std::move(destination)) {}
+
+ bool IsRange() const override { return false; }
+ std::string ToString() const override { return "addr(" + EncodeDestination(m_destination) + ")"; }
+ bool ToPrivateString(const SigningProvider& arg, std::string& out) const override { out = ToString(); return true; }
+ bool Expand(int pos, const SigningProvider& arg, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const override
+ {
+ output_scripts = std::vector<CScript>{GetScriptForDestination(m_destination)};
+ return true;
+ }
+};
+
+/** A parsed raw(H) descriptor. */
+class RawDescriptor final : public Descriptor
+{
+ CScript m_script;
+
+public:
+ RawDescriptor(CScript script) : m_script(std::move(script)) {}
+
+ bool IsRange() const override { return false; }
+ std::string ToString() const override { return "raw(" + HexStr(m_script.begin(), m_script.end()) + ")"; }
+ bool ToPrivateString(const SigningProvider& arg, std::string& out) const override { out = ToString(); return true; }
+ bool Expand(int pos, const SigningProvider& arg, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const override
+ {
+ output_scripts = std::vector<CScript>{m_script};
+ return true;
+ }
+};
+
+/** A parsed pk(P), pkh(P), or wpkh(P) descriptor. */
+class SingleKeyDescriptor final : public Descriptor
+{
+ const std::function<CScript(const CPubKey&)> m_script_fn;
+ const std::string m_fn_name;
+ std::unique_ptr<PubkeyProvider> m_provider;
+
+public:
+ SingleKeyDescriptor(std::unique_ptr<PubkeyProvider> prov, const std::function<CScript(const CPubKey&)>& fn, const std::string& name) : m_script_fn(fn), m_fn_name(name), m_provider(std::move(prov)) {}
+
+ bool IsRange() const override { return m_provider->IsRange(); }
+ std::string ToString() const override { return m_fn_name + "(" + m_provider->ToString() + ")"; }
+ bool ToPrivateString(const SigningProvider& arg, std::string& out) const override
+ {
+ std::string ret;
+ if (!m_provider->ToPrivateString(arg, ret)) return false;
+ out = m_fn_name + "(" + std::move(ret) + ")";
+ return true;
+ }
+ bool Expand(int pos, const SigningProvider& arg, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const override
+ {
+ CPubKey key;
+ if (!m_provider->GetPubKey(pos, arg, key)) return false;
+ output_scripts = std::vector<CScript>{m_script_fn(key)};
+ out.pubkeys.emplace(key.GetID(), std::move(key));
+ return true;
+ }
+};
+
+CScript P2PKHGetScript(const CPubKey& pubkey) { return GetScriptForDestination(pubkey.GetID()); }
+CScript P2PKGetScript(const CPubKey& pubkey) { return GetScriptForRawPubKey(pubkey); }
+CScript P2WPKHGetScript(const CPubKey& pubkey) { return GetScriptForDestination(WitnessV0KeyHash(pubkey.GetID())); }
+
+/** A parsed multi(...) descriptor. */
+class MultisigDescriptor : public Descriptor
+{
+ int m_threshold;
+ std::vector<std::unique_ptr<PubkeyProvider>> m_providers;
+
+public:
+ MultisigDescriptor(int threshold, std::vector<std::unique_ptr<PubkeyProvider>> providers) : m_threshold(threshold), m_providers(std::move(providers)) {}
+
+ bool IsRange() const override
+ {
+ for (const auto& p : m_providers) {
+ if (p->IsRange()) return true;
+ }
+ return false;
+ }
+
+ std::string ToString() const override
+ {
+ std::string ret = strprintf("multi(%i", m_threshold);
+ for (const auto& p : m_providers) {
+ ret += "," + p->ToString();
+ }
+ return std::move(ret) + ")";
+ }
+
+ bool ToPrivateString(const SigningProvider& arg, std::string& out) const override
+ {
+ std::string ret = strprintf("multi(%i", m_threshold);
+ for (const auto& p : m_providers) {
+ std::string sub;
+ if (!p->ToPrivateString(arg, sub)) return false;
+ ret += "," + std::move(sub);
+ }
+ out = std::move(ret) + ")";
+ return true;
+ }
+
+ bool Expand(int pos, const SigningProvider& arg, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const override
+ {
+ std::vector<CPubKey> pubkeys;
+ pubkeys.reserve(m_providers.size());
+ for (const auto& p : m_providers) {
+ CPubKey key;
+ if (!p->GetPubKey(pos, arg, key)) return false;
+ pubkeys.push_back(key);
+ }
+ for (const CPubKey& key : pubkeys) {
+ out.pubkeys.emplace(key.GetID(), std::move(key));
+ }
+ output_scripts = std::vector<CScript>{GetScriptForMultisig(m_threshold, pubkeys)};
+ return true;
+ }
+};
+
+/** A parsed sh(S) or wsh(S) descriptor. */
+class ConvertorDescriptor : public Descriptor
+{
+ const std::function<CScript(const CScript&)> m_convert_fn;
+ const std::string m_fn_name;
+ std::unique_ptr<Descriptor> m_descriptor;
+
+public:
+ ConvertorDescriptor(std::unique_ptr<Descriptor> descriptor, const std::function<CScript(const CScript&)>& fn, const std::string& name) : m_convert_fn(fn), m_fn_name(name), m_descriptor(std::move(descriptor)) {}
+
+ bool IsRange() const override { return m_descriptor->IsRange(); }
+ std::string ToString() const override { return m_fn_name + "(" + m_descriptor->ToString() + ")"; }
+ bool ToPrivateString(const SigningProvider& arg, std::string& out) const override
+ {
+ std::string ret;
+ if (!m_descriptor->ToPrivateString(arg, ret)) return false;
+ out = m_fn_name + "(" + std::move(ret) + ")";
+ return true;
+ }
+ bool Expand(int pos, const SigningProvider& arg, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const override
+ {
+ std::vector<CScript> sub;
+ if (!m_descriptor->Expand(pos, arg, sub, out)) return false;
+ output_scripts.clear();
+ for (const auto& script : sub) {
+ CScriptID id(script);
+ out.scripts.emplace(CScriptID(script), script);
+ output_scripts.push_back(m_convert_fn(script));
+ }
+ return true;
+ }
+};
+
+CScript ConvertP2SH(const CScript& script) { return GetScriptForDestination(CScriptID(script)); }
+CScript ConvertP2WSH(const CScript& script) { return GetScriptForDestination(WitnessV0ScriptHash(script)); }
+
+/** A parsed combo(P) descriptor. */
+class ComboDescriptor final : public Descriptor
+{
+ std::unique_ptr<PubkeyProvider> m_provider;
+
+public:
+ ComboDescriptor(std::unique_ptr<PubkeyProvider> provider) : m_provider(std::move(provider)) {}
+
+ bool IsRange() const override { return m_provider->IsRange(); }
+ std::string ToString() const override { return "combo(" + m_provider->ToString() + ")"; }
+ bool ToPrivateString(const SigningProvider& arg, std::string& out) const override
+ {
+ std::string ret;
+ if (!m_provider->ToPrivateString(arg, ret)) return false;
+ out = "combo(" + std::move(ret) + ")";
+ return true;
+ }
+ bool Expand(int pos, const SigningProvider& arg, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const override
+ {
+ CPubKey key;
+ if (!m_provider->GetPubKey(pos, arg, key)) return false;
+ CKeyID keyid = key.GetID();
+ {
+ CScript p2pk = GetScriptForRawPubKey(key);
+ CScript p2pkh = GetScriptForDestination(keyid);
+ output_scripts = std::vector<CScript>{std::move(p2pk), std::move(p2pkh)};
+ out.pubkeys.emplace(keyid, key);
+ }
+ if (key.IsCompressed()) {
+ CScript p2wpkh = GetScriptForDestination(WitnessV0KeyHash(keyid));
+ CScriptID p2wpkh_id(p2wpkh);
+ CScript p2sh_p2wpkh = GetScriptForDestination(p2wpkh_id);
+ out.scripts.emplace(p2wpkh_id, p2wpkh);
+ output_scripts.push_back(std::move(p2wpkh));
+ output_scripts.push_back(std::move(p2sh_p2wpkh));
+ }
+ return true;
+ }
+};
+
+////////////////////////////////////////////////////////////////////////////
+// Parser //
+////////////////////////////////////////////////////////////////////////////
+
+enum class ParseScriptContext {
+ TOP,
+ P2SH,
+ P2WSH,
+};
+
+/** Parse a constant. If succesful, sp is updated to skip the constant and return true. */
+bool Const(const std::string& str, Span<const char>& sp)
+{
+ if ((size_t)sp.size() >= str.size() && std::equal(str.begin(), str.end(), sp.begin())) {
+ sp = sp.subspan(str.size());
+ return true;
+ }
+ return false;
+}
+
+/** Parse a function call. If succesful, sp is updated to be the function's argument(s). */
+bool Func(const std::string& str, Span<const char>& sp)
+{
+ if ((size_t)sp.size() >= str.size() + 2 && sp[str.size()] == '(' && sp[sp.size() - 1] == ')' && std::equal(str.begin(), str.end(), sp.begin())) {
+ sp = sp.subspan(str.size() + 1, sp.size() - str.size() - 2);
+ return true;
+ }
+ return false;
+}
+
+/** Return the expression that sp begins with, and update sp to skip it. */
+Span<const char> Expr(Span<const char>& sp)
+{
+ int level = 0;
+ auto it = sp.begin();
+ while (it != sp.end()) {
+ if (*it == '(') {
+ ++level;
+ } else if (level && *it == ')') {
+ --level;
+ } else if (level == 0 && (*it == ')' || *it == ',')) {
+ break;
+ }
+ ++it;
+ }
+ Span<const char> ret = sp.first(it - sp.begin());
+ sp = sp.subspan(it - sp.begin());
+ return ret;
+}
+
+/** Split a string on every instance of sep, returning a vector. */
+std::vector<Span<const char>> Split(const Span<const char>& sp, char sep)
+{
+ std::vector<Span<const char>> ret;
+ auto it = sp.begin();
+ auto start = it;
+ while (it != sp.end()) {
+ if (*it == sep) {
+ ret.emplace_back(start, it);
+ start = it + 1;
+ }
+ ++it;
+ }
+ ret.emplace_back(start, it);
+ return ret;
+}
+
+/** Parse a key path, being passed a split list of elements (the first element is ignored). */
+bool ParseKeyPath(const std::vector<Span<const char>>& split, KeyPath& out)
+{
+ for (size_t i = 1; i < split.size(); ++i) {
+ Span<const char> elem = split[i];
+ bool hardened = false;
+ if (elem.size() > 0 && (elem[elem.size() - 1] == '\'' || elem[elem.size() - 1] == 'h')) {
+ elem = elem.first(elem.size() - 1);
+ hardened = true;
+ }
+ uint32_t p;
+ if (!ParseUInt32(std::string(elem.begin(), elem.end()), &p) || p > 0x7FFFFFFFUL) return false;
+ out.push_back(p | (((uint32_t)hardened) << 31));
+ }
+ return true;
+}
+
+std::unique_ptr<PubkeyProvider> ParsePubkey(const Span<const char>& sp, bool permit_uncompressed, FlatSigningProvider& out)
+{
+ auto split = Split(sp, '/');
+ std::string str(split[0].begin(), split[0].end());
+ if (split.size() == 1) {
+ if (IsHex(str)) {
+ std::vector<unsigned char> data = ParseHex(str);
+ CPubKey pubkey(data);
+ if (pubkey.IsFullyValid() && (permit_uncompressed || pubkey.IsCompressed())) return MakeUnique<ConstPubkeyProvider>(pubkey);
+ }
+ CKey key = DecodeSecret(str);
+ if (key.IsValid() && (permit_uncompressed || key.IsCompressed())) {
+ CPubKey pubkey = key.GetPubKey();
+ out.keys.emplace(pubkey.GetID(), key);
+ return MakeUnique<ConstPubkeyProvider>(pubkey);
+ }
+ }
+ CExtKey extkey = DecodeExtKey(str);
+ CExtPubKey extpubkey = DecodeExtPubKey(str);
+ if (!extkey.key.IsValid() && !extpubkey.pubkey.IsValid()) return nullptr;
+ KeyPath path;
+ DeriveType type = DeriveType::NO;
+ if (split.back() == MakeSpan("*").first(1)) {
+ split.pop_back();
+ type = DeriveType::UNHARDENED;
+ } else if (split.back() == MakeSpan("*'").first(2) || split.back() == MakeSpan("*h").first(2)) {
+ split.pop_back();
+ type = DeriveType::HARDENED;
+ }
+ if (!ParseKeyPath(split, path)) return nullptr;
+ if (extkey.key.IsValid()) {
+ extpubkey = extkey.Neuter();
+ out.keys.emplace(extpubkey.pubkey.GetID(), extkey.key);
+ }
+ return MakeUnique<BIP32PubkeyProvider>(extpubkey, std::move(path), type);
+}
+
+/** Parse a script in a particular context. */
+std::unique_ptr<Descriptor> ParseScript(Span<const char>& sp, ParseScriptContext ctx, FlatSigningProvider& out)
+{
+ auto expr = Expr(sp);
+ if (Func("pk", expr)) {
+ auto pubkey = ParsePubkey(expr, ctx != ParseScriptContext::P2WSH, out);
+ if (!pubkey) return nullptr;
+ return MakeUnique<SingleKeyDescriptor>(std::move(pubkey), P2PKGetScript, "pk");
+ }
+ if (Func("pkh", expr)) {
+ auto pubkey = ParsePubkey(expr, ctx != ParseScriptContext::P2WSH, out);
+ if (!pubkey) return nullptr;
+ return MakeUnique<SingleKeyDescriptor>(std::move(pubkey), P2PKHGetScript, "pkh");
+ }
+ if (ctx == ParseScriptContext::TOP && Func("combo", expr)) {
+ auto pubkey = ParsePubkey(expr, true, out);
+ if (!pubkey) return nullptr;
+ return MakeUnique<ComboDescriptor>(std::move(pubkey));
+ }
+ if (Func("multi", expr)) {
+ auto threshold = Expr(expr);
+ uint32_t thres;
+ std::vector<std::unique_ptr<PubkeyProvider>> providers;
+ if (!ParseUInt32(std::string(threshold.begin(), threshold.end()), &thres)) return nullptr;
+ size_t script_size = 0;
+ while (expr.size()) {
+ if (!Const(",", expr)) return nullptr;
+ auto arg = Expr(expr);
+ auto pk = ParsePubkey(arg, ctx != ParseScriptContext::P2WSH, out);
+ if (!pk) return nullptr;
+ script_size += pk->GetSize() + 1;
+ providers.emplace_back(std::move(pk));
+ }
+ if (providers.size() < 1 || providers.size() > 16 || thres < 1 || thres > providers.size()) return nullptr;
+ if (ctx == ParseScriptContext::TOP) {
+ if (providers.size() > 3) return nullptr; // Not more than 3 pubkeys for raw multisig
+ }
+ if (ctx == ParseScriptContext::P2SH) {
+ if (script_size + 3 > 520) return nullptr; // Enforce P2SH script size limit
+ }
+ return MakeUnique<MultisigDescriptor>(thres, std::move(providers));
+ }
+ if (ctx != ParseScriptContext::P2WSH && Func("wpkh", expr)) {
+ auto pubkey = ParsePubkey(expr, false, out);
+ if (!pubkey) return nullptr;
+ return MakeUnique<SingleKeyDescriptor>(std::move(pubkey), P2WPKHGetScript, "wpkh");
+ }
+ if (ctx == ParseScriptContext::TOP && Func("sh", expr)) {
+ auto desc = ParseScript(expr, ParseScriptContext::P2SH, out);
+ if (!desc || expr.size()) return nullptr;
+ return MakeUnique<ConvertorDescriptor>(std::move(desc), ConvertP2SH, "sh");
+ }
+ if (ctx != ParseScriptContext::P2WSH && Func("wsh", expr)) {
+ auto desc = ParseScript(expr, ParseScriptContext::P2WSH, out);
+ if (!desc || expr.size()) return nullptr;
+ return MakeUnique<ConvertorDescriptor>(std::move(desc), ConvertP2WSH, "wsh");
+ }
+ if (ctx == ParseScriptContext::TOP && Func("addr", expr)) {
+ CTxDestination dest = DecodeDestination(std::string(expr.begin(), expr.end()));
+ if (!IsValidDestination(dest)) return nullptr;
+ return MakeUnique<AddressDescriptor>(std::move(dest));
+ }
+ if (ctx == ParseScriptContext::TOP && Func("raw", expr)) {
+ std::string str(expr.begin(), expr.end());
+ if (!IsHex(str)) return nullptr;
+ auto bytes = ParseHex(str);
+ return MakeUnique<RawDescriptor>(CScript(bytes.begin(), bytes.end()));
+ }
+ return nullptr;
+}
+
+} // namespace
+
+std::unique_ptr<Descriptor> Parse(const std::string& descriptor, FlatSigningProvider& out)
+{
+ Span<const char> sp(descriptor.data(), descriptor.size());
+ auto ret = ParseScript(sp, ParseScriptContext::TOP, out);
+ if (sp.size() == 0 && ret) return ret;
+ return nullptr;
+}
diff --git a/src/script/descriptor.h b/src/script/descriptor.h
new file mode 100644
index 0000000000..e079c72e92
--- /dev/null
+++ b/src/script/descriptor.h
@@ -0,0 +1,102 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_SCRIPT_DESCRIPTOR_H
+#define BITCOIN_SCRIPT_DESCRIPTOR_H
+
+#include <script/script.h>
+#include <script/sign.h>
+
+#include <vector>
+
+// Descriptors are strings that describe a set of scriptPubKeys, together with
+// all information necessary to solve them. By combining all information into
+// one, they avoid the need to separately import keys and scripts.
+//
+// Descriptors may be ranged, which occurs when the public keys inside are
+// specified in the form of HD chains (xpubs).
+//
+// Descriptors always represent public information - public keys and scripts -
+// but in cases where private keys need to be conveyed along with a descriptor,
+// they can be included inside by changing public keys to private keys (WIF
+// format), and changing xpubs by xprvs.
+//
+// 1. Examples
+//
+// A P2PK descriptor with a fixed public key:
+// - pk(0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798)
+//
+// A P2SH-P2WSH-P2PKH descriptor with a fixed public key:
+// - sh(wsh(pkh(02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13)))
+//
+// A bare 1-of-2 multisig descriptor:
+// - multi(1,022f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4,025cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc)
+//
+// A chain of P2PKH outputs (this needs the corresponding private key to derive):
+// - pkh(xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw/1'/2/*)
+//
+// 2. Grammar description:
+//
+// X: xpub or xprv encoded extended key
+// I: decimal encoded integer
+// H: Hex encoded byte array
+// A: Address in P2PKH, P2SH, or Bech32 encoding
+//
+// S (Scripts):
+// * pk(P): Pay-to-pubkey (P2PK) output for public key P.
+// * pkh(P): Pay-to-pubkey-hash (P2PKH) output for public key P.
+// * wpkh(P): Pay-to-witness-pubkey-hash (P2WPKH) output for public key P.
+// * sh(S): Pay-to-script-hash (P2SH) output for script S
+// * wsh(S): Pay-to-witness-script-hash (P2WSH) output for script S
+// * combo(P): combination of P2PK, P2PKH, P2WPKH, and P2SH-P2WPKH for public key P.
+// * multi(I,L): k-of-n multisig for given public keys
+// * addr(A): Output to address
+// * raw(H): scriptPubKey with raw bytes
+//
+// P (Public keys):
+// * H: fixed public key (or WIF-encoded private key)
+// * E: extended public key
+// * E/*: (ranged) all unhardened direct children of an extended public key
+// * E/*': (ranged) all hardened direct children of an extended public key
+//
+// L (Comma-separated lists of public keys):
+// * P
+// * L,P
+//
+// E (Extended public keys):
+// * X
+// * E/I: unhardened child
+// * E/I': hardened child
+// * E/Ih: hardened child (alternative notation)
+//
+// The top level is S.
+
+/** Interface for parsed descriptor objects. */
+struct Descriptor {
+ virtual ~Descriptor() = default;
+
+ /** Whether the expansion of this descriptor depends on the position. */
+ virtual bool IsRange() const = 0;
+
+ /** Convert the descriptor back to a string, undoing parsing. */
+ virtual std::string ToString() const = 0;
+
+ /** Convert the descriptor to a private string. This fails if the provided provider does not have the relevant private keys. */
+ virtual bool ToPrivateString(const SigningProvider& provider, std::string& out) const = 0;
+
+ /** Expand a descriptor at a specified position.
+ *
+ * pos: the position at which to expand the descriptor. If IsRange() is false, this is ignored.
+ * provider: the provider to query for private keys in case of hardened derivation.
+ * output_script: the expanded scriptPubKeys will be put here.
+ * out: scripts and public keys necessary for solving the expanded scriptPubKeys will be put here (may be equal to provider).
+ */
+ virtual bool Expand(int pos, const SigningProvider& provider, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const = 0;
+};
+
+/** Parse a descriptor string. Included private keys are put in out. Returns nullptr if parsing fails. */
+std::unique_ptr<Descriptor> Parse(const std::string& descriptor, FlatSigningProvider& out);
+
+#endif // BITCOIN_SCRIPT_DESCRIPTOR_H
+
diff --git a/src/script/sign.cpp b/src/script/sign.cpp
index d10b1c4fd7..fa09adbaf8 100644
--- a/src/script/sign.cpp
+++ b/src/script/sign.cpp
@@ -11,7 +11,6 @@
#include <script/standard.h>
#include <uint256.h>
-
typedef std::vector<unsigned char> valtype;
MutableTransactionSignatureCreator::MutableTransactionSignatureCreator(const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn) : txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), amount(amountIn), checker(txTo, nIn, amountIn) {}
@@ -437,6 +436,18 @@ public:
return true;
}
};
+
+template<typename M, typename K, typename V>
+bool LookupHelper(const M& map, const K& key, V& value)
+{
+ auto it = map.find(key);
+ if (it != map.end()) {
+ value = it->second;
+ return true;
+ }
+ return false;
+}
+
}
const BaseSignatureCreator& DUMMY_SIGNATURE_CREATOR = DummySignatureCreator();
@@ -460,7 +471,6 @@ bool IsSolvable(const SigningProvider& provider, const CScript& script)
return false;
}
-
bool PartiallySignedTransaction::IsNull() const
{
return !tx && inputs.empty() && outputs.empty() && unknown.empty();
@@ -618,3 +628,19 @@ bool PublicOnlySigningProvider::GetPubKey(const CKeyID &address, CPubKey& pubkey
{
return m_provider->GetPubKey(address, pubkey);
}
+
+bool FlatSigningProvider::GetCScript(const CScriptID& scriptid, CScript& script) const { return LookupHelper(scripts, scriptid, script); }
+bool FlatSigningProvider::GetPubKey(const CKeyID& keyid, CPubKey& pubkey) const { return LookupHelper(pubkeys, keyid, pubkey); }
+bool FlatSigningProvider::GetKey(const CKeyID& keyid, CKey& key) const { return LookupHelper(keys, keyid, key); }
+
+FlatSigningProvider Merge(const FlatSigningProvider& a, const FlatSigningProvider& b)
+{
+ FlatSigningProvider ret;
+ ret.scripts = a.scripts;
+ ret.scripts.insert(b.scripts.begin(), b.scripts.end());
+ ret.pubkeys = a.pubkeys;
+ ret.pubkeys.insert(b.pubkeys.begin(), b.pubkeys.end());
+ ret.keys = a.keys;
+ ret.keys.insert(b.keys.begin(), b.keys.end());
+ return ret;
+}
diff --git a/src/script/sign.h b/src/script/sign.h
index d12d0b5874..96ef59fbe8 100644
--- a/src/script/sign.h
+++ b/src/script/sign.h
@@ -43,6 +43,19 @@ public:
bool GetPubKey(const CKeyID &address, CPubKey& pubkey) const;
};
+struct FlatSigningProvider final : public SigningProvider
+{
+ std::map<CScriptID, CScript> scripts;
+ std::map<CKeyID, CPubKey> pubkeys;
+ std::map<CKeyID, CKey> keys;
+
+ bool GetCScript(const CScriptID& scriptid, CScript& script) const override;
+ bool GetPubKey(const CKeyID& keyid, CPubKey& pubkey) const override;
+ bool GetKey(const CKeyID& keyid, CKey& key) const override;
+};
+
+FlatSigningProvider Merge(const FlatSigningProvider& a, const FlatSigningProvider& b);
+
/** Interface for signature creators. */
class BaseSignatureCreator {
public:
diff --git a/src/span.h b/src/span.h
index 707fc21918..77de059fa6 100644
--- a/src/span.h
+++ b/src/span.h
@@ -7,6 +7,7 @@
#include <type_traits>
#include <cstddef>
+#include <algorithm>
/** A Span is an object that can refer to a contiguous sequence of objects.
*
@@ -21,9 +22,25 @@ class Span
public:
constexpr Span() noexcept : m_data(nullptr), m_size(0) {}
constexpr Span(C* data, std::ptrdiff_t size) noexcept : m_data(data), m_size(size) {}
+ constexpr Span(C* data, C* end) noexcept : m_data(data), m_size(end - data) {}
constexpr C* data() const noexcept { return m_data; }
+ constexpr C* begin() const noexcept { return m_data; }
+ constexpr C* end() const noexcept { return m_data + m_size; }
constexpr std::ptrdiff_t size() const noexcept { return m_size; }
+ constexpr C& operator[](std::ptrdiff_t pos) const noexcept { return m_data[pos]; }
+
+ constexpr Span<C> subspan(std::ptrdiff_t offset) const noexcept { return Span<C>(m_data + offset, m_size - offset); }
+ constexpr Span<C> subspan(std::ptrdiff_t offset, std::ptrdiff_t count) const noexcept { return Span<C>(m_data + offset, count); }
+ constexpr Span<C> first(std::ptrdiff_t count) const noexcept { return Span<C>(m_data, count); }
+ constexpr Span<C> last(std::ptrdiff_t count) const noexcept { return Span<C>(m_data + m_size - count, count); }
+
+ friend constexpr bool operator==(const Span& a, const Span& b) noexcept { return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin()); }
+ friend constexpr bool operator!=(const Span& a, const Span& b) noexcept { return !(a == b); }
+ friend constexpr bool operator<(const Span& a, const Span& b) noexcept { return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end()); }
+ friend constexpr bool operator<=(const Span& a, const Span& b) noexcept { return !(b < a); }
+ friend constexpr bool operator>(const Span& a, const Span& b) noexcept { return (b < a); }
+ friend constexpr bool operator>=(const Span& a, const Span& b) noexcept { return !(a < b); }
};
/** Create a span to a container exposing data() and size().
@@ -34,6 +51,9 @@ public:
*
* std::span will have a constructor that implements this functionality directly.
*/
+template<typename A, int N>
+constexpr Span<A> MakeSpan(A (&a)[N]) { return Span<A>(a, N); }
+
template<typename V>
constexpr Span<typename std::remove_pointer<decltype(std::declval<V>().data())>::type> MakeSpan(V& v) { return Span<typename std::remove_pointer<decltype(std::declval<V>().data())>::type>(v.data(), v.size()); }
diff --git a/src/test/blockencodings_tests.cpp b/src/test/blockencodings_tests.cpp
index 3dd5356164..df839884fe 100644
--- a/src/test/blockencodings_tests.cpp
+++ b/src/test/blockencodings_tests.cpp
@@ -62,8 +62,8 @@ BOOST_AUTO_TEST_CASE(SimpleRoundTripTest)
TestMemPoolEntryHelper entry;
CBlock block(BuildBlockTestCase());
- pool.addUnchecked(block.vtx[2]->GetHash(), entry.FromTx(block.vtx[2]));
LOCK(pool.cs);
+ pool.addUnchecked(block.vtx[2]->GetHash(), entry.FromTx(block.vtx[2]));
BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
// Do a simple ShortTxIDs RT
@@ -162,8 +162,8 @@ BOOST_AUTO_TEST_CASE(NonCoinbasePreforwardRTTest)
TestMemPoolEntryHelper entry;
CBlock block(BuildBlockTestCase());
- pool.addUnchecked(block.vtx[2]->GetHash(), entry.FromTx(block.vtx[2]));
LOCK(pool.cs);
+ pool.addUnchecked(block.vtx[2]->GetHash(), entry.FromTx(block.vtx[2]));
BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
uint256 txhash;
@@ -232,8 +232,8 @@ BOOST_AUTO_TEST_CASE(SufficientPreforwardRTTest)
TestMemPoolEntryHelper entry;
CBlock block(BuildBlockTestCase());
- pool.addUnchecked(block.vtx[1]->GetHash(), entry.FromTx(block.vtx[1]));
LOCK(pool.cs);
+ pool.addUnchecked(block.vtx[1]->GetHash(), entry.FromTx(block.vtx[1]));
BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[1]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
uint256 txhash;
diff --git a/src/test/descriptor_tests.cpp b/src/test/descriptor_tests.cpp
new file mode 100644
index 0000000000..f189222be8
--- /dev/null
+++ b/src/test/descriptor_tests.cpp
@@ -0,0 +1,163 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <vector>
+#include <string>
+#include <script/sign.h>
+#include <script/standard.h>
+#include <test/test_bitcoin.h>
+#include <boost/test/unit_test.hpp>
+#include <script/descriptor.h>
+#include <utilstrencodings.h>
+
+namespace {
+
+void CheckUnparsable(const std::string& prv, const std::string& pub)
+{
+ FlatSigningProvider keys_priv, keys_pub;
+ auto parse_priv = Parse(prv, keys_priv);
+ auto parse_pub = Parse(pub, keys_pub);
+ BOOST_CHECK(!parse_priv);
+ BOOST_CHECK(!parse_pub);
+}
+
+constexpr int DEFAULT = 0;
+constexpr int RANGE = 1; // Expected to be ranged descriptor
+constexpr int HARDENED = 2; // Derivation needs access to private keys
+constexpr int UNSOLVABLE = 4; // This descriptor is not expected to be solvable
+constexpr int SIGNABLE = 8; // We can sign with this descriptor (this is not true when actual BIP32 derivation is used, as that's not integrated in our signing code)
+
+std::string MaybeUseHInsteadOfApostrophy(std::string ret)
+{
+ if (InsecureRandBool()) {
+ while (true) {
+ auto it = ret.find("'");
+ if (it != std::string::npos) {
+ ret[it] = 'h';
+ } else {
+ break;
+ }
+ }
+ }
+ return ret;
+}
+
+void Check(const std::string& prv, const std::string& pub, int flags, const std::vector<std::vector<std::string>>& scripts)
+{
+ FlatSigningProvider keys_priv, keys_pub;
+
+ // Check that parsing succeeds.
+ auto parse_priv = Parse(MaybeUseHInsteadOfApostrophy(prv), keys_priv);
+ auto parse_pub = Parse(MaybeUseHInsteadOfApostrophy(pub), keys_pub);
+ BOOST_CHECK(parse_priv);
+ BOOST_CHECK(parse_pub);
+
+ // Check private keys are extracted from the private version but not the public one.
+ BOOST_CHECK(keys_priv.keys.size());
+ BOOST_CHECK(!keys_pub.keys.size());
+
+ // Check that both versions serialize back to the public version.
+ std::string pub1 = parse_priv->ToString();
+ std::string pub2 = parse_priv->ToString();
+ BOOST_CHECK_EQUAL(pub, pub1);
+ BOOST_CHECK_EQUAL(pub, pub2);
+
+ // Check that both can be serialized with private key back to the private version, but not without private key.
+ std::string prv1, prv2;
+ BOOST_CHECK(parse_priv->ToPrivateString(keys_priv, prv1));
+ BOOST_CHECK_EQUAL(prv, prv1);
+ BOOST_CHECK(!parse_priv->ToPrivateString(keys_pub, prv1));
+ BOOST_CHECK(parse_pub->ToPrivateString(keys_priv, prv1));
+ BOOST_CHECK_EQUAL(prv, prv1);
+ BOOST_CHECK(!parse_pub->ToPrivateString(keys_pub, prv1));
+
+ // Check whether IsRange on both returns the expected result
+ BOOST_CHECK_EQUAL(parse_pub->IsRange(), (flags & RANGE) != 0);
+ BOOST_CHECK_EQUAL(parse_priv->IsRange(), (flags & RANGE) != 0);
+
+
+ // Is not ranged descriptor, only a single result is expected.
+ if (!(flags & RANGE)) assert(scripts.size() == 1);
+
+ size_t max = (flags & RANGE) ? scripts.size() : 3;
+ for (size_t i = 0; i < max; ++i) {
+ const auto& ref = scripts[(flags & RANGE) ? i : 0];
+ for (int t = 0; t < 2; ++t) {
+ FlatSigningProvider key_provider = (flags & HARDENED) ? keys_priv : keys_pub;
+ FlatSigningProvider script_provider;
+ std::vector<CScript> spks;
+ BOOST_CHECK((t ? parse_priv : parse_pub)->Expand(i, key_provider, spks, script_provider));
+ BOOST_CHECK_EQUAL(spks.size(), ref.size());
+ for (size_t n = 0; n < spks.size(); ++n) {
+ BOOST_CHECK_EQUAL(ref[n], HexStr(spks[n].begin(), spks[n].end()));
+ BOOST_CHECK_EQUAL(IsSolvable(Merge(key_provider, script_provider), spks[n]), (flags & UNSOLVABLE) == 0);
+
+ if (flags & SIGNABLE) {
+ CMutableTransaction spend;
+ spend.vin.resize(1);
+ spend.vout.resize(1);
+ BOOST_CHECK_MESSAGE(SignSignature(Merge(keys_priv, script_provider), spks[n], spend, 0, 1, SIGHASH_ALL), prv);
+ }
+ }
+
+ }
+ }
+}
+
+}
+
+BOOST_FIXTURE_TEST_SUITE(descriptor_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(descriptor_test)
+{
+ // Basic single-key compressed
+ Check("combo(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "combo(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac","76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac","00149a1c78a507689f6f54b847ad1cef1e614ee23f1e","a91484ab21b1b2fd065d4504ff693d832434b6108d7b87"}});
+ Check("pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac"}});
+ Check("pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac"}});
+ Check("wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"00149a1c78a507689f6f54b847ad1cef1e614ee23f1e"}});
+ Check("sh(wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"a91484ab21b1b2fd065d4504ff693d832434b6108d7b87"}});
+
+ // Basic single-key uncompressed
+ Check("combo(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "combo(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235ac","76a914b5bd079c4d57cc7fc28ecf8213a6b791625b818388ac"}});
+ Check("pk(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "pk(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235ac"}});
+ Check("pkh(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "pkh(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"76a914b5bd079c4d57cc7fc28ecf8213a6b791625b818388ac"}});
+ CheckUnparsable("wpkh(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "wpkh(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)"); // No uncompressed keys in witness
+ CheckUnparsable("wsh(pk(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss))", "wsh(pk(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235))"); // No uncompressed keys in witness
+ CheckUnparsable("sh(wpkh(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss))", "sh(wpkh(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235))"); // No uncompressed keys in witness
+
+ // Some unconventional single-key constructions
+ Check("sh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"a9141857af51a5e516552b3086430fd8ce55f7c1a52487"}});
+ Check("sh(pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"a9141a31ad23bf49c247dd531a623c2ef57da3c400c587"}});
+ Check("wsh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "wsh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"00202e271faa2325c199d25d22e1ead982e45b64eeb4f31e73dbdf41bd4b5fec23fa"}});
+ Check("wsh(pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "wsh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"0020338e023079b91c58571b20e602d7805fb808c22473cbc391a41b1bd3a192e75b"}});
+ Check("sh(wsh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "sh(wsh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))", SIGNABLE, {{"a91472d0c5a3bfad8c3e7bd5303a72b94240e80b6f1787"}});
+ Check("sh(wsh(pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "sh(wsh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))", SIGNABLE, {{"a914b61b92e2ca21bac1e72a3ab859a742982bea960a87"}});
+
+ // Versions with BIP32 derivations
+ Check("combo(xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)", "combo(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)", SIGNABLE, {{"2102d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0ac","76a91431a507b815593dfc51ffc7245ae7e5aee304246e88ac","001431a507b815593dfc51ffc7245ae7e5aee304246e","a9142aafb926eb247cb18240a7f4c07983ad1f37922687"}});
+ Check("pk(xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0)", "pk(xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0)", DEFAULT, {{"210379e45b3cf75f9c5f9befd8e9506fb962f6a9d185ac87001ec44a8d3df8d4a9e3ac"}});
+ Check("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0)", HARDENED, {{"76a914ebdc90806a9c4356c1c88e42216611e1cb4c1c1788ac"}});
+ Check("wpkh(xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*)", "wpkh(xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*)", RANGE, {{"0014326b2249e3a25d5dc60935f044ee835d090ba859"},{"0014af0bd98abc2f2cae66e36896a39ffe2d32984fb7"},{"00141fa798efd1cbf95cebf912c031b8a4a6e9fb9f27"}});
+ Check("sh(wpkh(xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "sh(wpkh(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", RANGE | HARDENED, {{"a9149a4d9901d6af519b2a23d4a2f51650fcba87ce7b87"},{"a914bed59fc0024fae941d6e20a3b44a109ae740129287"},{"a9148483aa1116eb9c05c482a72bada4b1db24af654387"}});
+ Check("combo(xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334/*)", "combo(xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV/*)", RANGE, {{"2102df12b7035bdac8e3bab862a3a83d06ea6b17b6753d52edecba9be46f5d09e076ac","76a914f90e3178ca25f2c808dc76624032d352fdbdfaf288ac","0014f90e3178ca25f2c808dc76624032d352fdbdfaf2","a91408f3ea8c68d4a7585bf9e8bda226723f70e445f087"},{"21032869a233c9adff9a994e4966e5b821fd5bac066da6c3112488dc52383b4a98ecac","76a914a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b788ac","0014a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b7","a91473e39884cb71ae4e5ac9739e9225026c99763e6687"}});
+ CheckUnparsable("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483648)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483648)"); // BIP 32 path element overflow
+
+ // Multisig constructions
+ Check("multi(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "multi(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}});
+ Check("sh(multi(2,xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))", "sh(multi(2,xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}});
+ Check("wsh(multi(2,xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", HARDENED | RANGE, {{"0020b92623201f3bb7c3771d45b2ad1d0351ea8fbf8cfe0a0e570264e1075fa1948f"},{"002036a08bbe4923af41cf4316817c93b8d37e2f635dd25cfff06bd50df6ae7ea203"},{"0020a96e7ab4607ca6b261bfe3245ffda9c746b28d3f59e83d34820ec0e2b36c139c"}});
+ Check("sh(wsh(multi(16,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9)))","sh(wsh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232)))", SIGNABLE, {{"a9147fc63e13dc25e8a95a3cee3d9a714ac3afd96f1e87"}});
+ CheckUnparsable("sh(multi(16,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9))","sh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232))"); // P2SH does not fit 16 compressed pubkeys in a redeemscript
+
+ // Check for invalid nesting of structures
+ CheckUnparsable("sh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "sh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)"); // P2SH needs a script, not a key
+ CheckUnparsable("sh(combo(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(combo(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))"); // Old must be top level
+ CheckUnparsable("wsh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "wsh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)"); // P2WSH needs a script, not a key
+ CheckUnparsable("wsh(wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "wsh(wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))"); // Cannot embed witness inside witness
+ CheckUnparsable("wsh(sh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "wsh(sh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))"); // Cannot embed P2SH inside P2WSH
+ CheckUnparsable("sh(sh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "sh(sh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))"); // Cannot embed P2SH inside P2SH
+ CheckUnparsable("wsh(wsh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "wsh(wsh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))"); // Cannot embed P2WSH inside P2WSH
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp
index e2d76dc293..fb80599af7 100644
--- a/src/test/mempool_tests.cpp
+++ b/src/test/mempool_tests.cpp
@@ -55,6 +55,7 @@ BOOST_AUTO_TEST_CASE(MempoolRemoveTest)
CTxMemPool testPool;
+ LOCK(testPool.cs);
// Nothing in pool, remove should do nothing:
unsigned int poolSize = testPool.size();
@@ -119,6 +120,7 @@ static void CheckSort(CTxMemPool &pool, std::vector<std::string> &sortedOrder) E
BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
{
CTxMemPool pool;
+ LOCK(pool.cs);
TestMemPoolEntryHelper entry;
/* 3rd highest fee */
@@ -165,7 +167,6 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
sortedOrder[2] = tx1.GetHash().ToString(); // 10000
sortedOrder[3] = tx4.GetHash().ToString(); // 15000
sortedOrder[4] = tx2.GetHash().ToString(); // 20000
- LOCK(pool.cs);
CheckSort<descendant_score>(pool, sortedOrder);
/* low fee but with high fee child */
@@ -292,6 +293,7 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest)
{
CTxMemPool pool;
+ LOCK(pool.cs);
TestMemPoolEntryHelper entry;
/* 3rd highest fee */
@@ -347,7 +349,6 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest)
}
sortedOrder[4] = tx3.GetHash().ToString(); // 0
- LOCK(pool.cs);
CheckSort<ancestor_score>(pool, sortedOrder);
/* low fee parent with high fee child */
@@ -421,6 +422,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest)
BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
{
CTxMemPool pool;
+ LOCK(pool.cs);
TestMemPoolEntryHelper entry;
CMutableTransaction tx1 = CMutableTransaction();
@@ -593,6 +595,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests)
size_t ancestors, descendants;
CTxMemPool pool;
+ LOCK(pool.cs);
TestMemPoolEntryHelper entry;
/* Base transaction */
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index 10c7fd00e8..e2424f012d 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -99,7 +99,7 @@ static bool TestSequenceLocks(const CTransaction &tx, int flags)
// Test suite for ancestor feerate transaction selection.
// Implemented as an additional function, rather than a separate test case,
// to allow reusing the blockchain created in CreateNewBlock_validity.
-static void TestPackageSelection(const CChainParams& chainparams, CScript scriptPubKey, std::vector<CTransactionRef>& txFirst)
+static void TestPackageSelection(const CChainParams& chainparams, const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst) EXCLUSIVE_LOCKS_REQUIRED(::mempool.cs)
{
// Test the ancestor feerate transaction selection.
TestMemPoolEntryHelper entry;
@@ -253,6 +253,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
}
LOCK(cs_main);
+ LOCK(::mempool.cs);
// Just to make sure we can still make simple blocks
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
diff --git a/src/test/policyestimator_tests.cpp b/src/test/policyestimator_tests.cpp
index 8d288ec993..e45fb6d17e 100644
--- a/src/test/policyestimator_tests.cpp
+++ b/src/test/policyestimator_tests.cpp
@@ -18,6 +18,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
{
CBlockPolicyEstimator feeEst;
CTxMemPool mpool(&feeEst);
+ LOCK(mpool.cs);
TestMemPoolEntryHelper entry;
CAmount basefee(2000);
CAmount deltaFee(100);
diff --git a/src/test/scheduler_tests.cpp b/src/test/scheduler_tests.cpp
index 179df7dd38..b1ea4b6fab 100644
--- a/src/test/scheduler_tests.cpp
+++ b/src/test/scheduler_tests.cpp
@@ -65,7 +65,7 @@ BOOST_AUTO_TEST_CASE(manythreads)
size_t nTasks = microTasks.getQueueInfo(first, last);
BOOST_CHECK(nTasks == 0);
- for (int i = 0; i < 100; i++) {
+ for (int i = 0; i < 100; ++i) {
boost::chrono::system_clock::time_point t = now + boost::chrono::microseconds(randomMsec(rng));
boost::chrono::system_clock::time_point tReschedule = now + boost::chrono::microseconds(500 + randomMsec(rng));
int whichCounter = zeroToNine(rng);
@@ -112,4 +112,46 @@ BOOST_AUTO_TEST_CASE(manythreads)
BOOST_CHECK_EQUAL(counterSum, 200);
}
+BOOST_AUTO_TEST_CASE(singlethreadedscheduler_ordered)
+{
+ CScheduler scheduler;
+
+ // each queue should be well ordered with respect to itself but not other queues
+ SingleThreadedSchedulerClient queue1(&scheduler);
+ SingleThreadedSchedulerClient queue2(&scheduler);
+
+ // create more threads than queues
+ // if the queues only permit execution of one task at once then
+ // the extra threads should effectively be doing nothing
+ // if they don't we'll get out of order behaviour
+ boost::thread_group threads;
+ for (int i = 0; i < 5; ++i) {
+ threads.create_thread(boost::bind(&CScheduler::serviceQueue, &scheduler));
+ }
+
+ // these are not atomic, if SinglethreadedSchedulerClient prevents
+ // parallel execution at the queue level no synchronization should be required here
+ int counter1 = 0;
+ int counter2 = 0;
+
+ // just simply count up on each queue - if execution is properly ordered then
+ // the callbacks should run in exactly the order in which they were enqueued
+ for (int i = 0; i < 100; ++i) {
+ queue1.AddToProcessQueue([i, &counter1]() {
+ BOOST_CHECK_EQUAL(i, counter1++);
+ });
+
+ queue2.AddToProcessQueue([i, &counter2]() {
+ BOOST_CHECK_EQUAL(i, counter2++);
+ });
+ }
+
+ // finish up
+ scheduler.stop(true);
+ threads.join_all();
+
+ BOOST_CHECK_EQUAL(counter1, 100);
+ BOOST_CHECK_EQUAL(counter2, 100);
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index 9d705e3d23..d68c38ad4e 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -151,8 +151,6 @@ void CTxMemPool::UpdateTransactionsFromBlock(const std::vector<uint256> &vHashes
bool CTxMemPool::CalculateMemPoolAncestors(const CTxMemPoolEntry &entry, setEntries &setAncestors, uint64_t limitAncestorCount, uint64_t limitAncestorSize, uint64_t limitDescendantCount, uint64_t limitDescendantSize, std::string &errString, bool fSearchForParents /* = true */) const
{
- LOCK(cs);
-
setEntries parentHashes;
const CTransaction &tx = entry.GetTx();
@@ -363,7 +361,6 @@ void CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry,
// Add to memory pool without checking anything.
// Used by AcceptToMemoryPool(), which DOES do
// all the appropriate checks.
- LOCK(cs);
indexed_transaction_set::iterator newit = mapTx.insert(entry).first;
mapLinks.insert(make_pair(newit, TxLinks()));
@@ -933,7 +930,6 @@ int CTxMemPool::Expire(int64_t time) {
void CTxMemPool::addUnchecked(const uint256&hash, const CTxMemPoolEntry &entry, bool validFeeEstimate)
{
- LOCK(cs);
setEntries setAncestors;
uint64_t nNoLimit = std::numeric_limits<uint64_t>::max();
std::string dummy;
diff --git a/src/txmempool.h b/src/txmempool.h
index bb676cf05d..0feea08f0b 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -539,8 +539,8 @@ public:
// Note that addUnchecked is ONLY called from ATMP outside of tests
// and any other callers may break wallet's in-mempool tracking (due to
// lack of CValidationInterface::TransactionAddedToMempool callbacks).
- void addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, bool validFeeEstimate = true);
- void addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, setEntries &setAncestors, bool validFeeEstimate = true);
+ void addUnchecked(const uint256& hash, const CTxMemPoolEntry& entry, bool validFeeEstimate = true) EXCLUSIVE_LOCKS_REQUIRED(cs);
+ void addUnchecked(const uint256& hash, const CTxMemPoolEntry& entry, setEntries& setAncestors, bool validFeeEstimate = true) EXCLUSIVE_LOCKS_REQUIRED(cs);
void removeRecursive(const CTransaction &tx, MemPoolRemovalReason reason = MemPoolRemovalReason::UNKNOWN);
void removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags);
@@ -596,7 +596,7 @@ public:
* fSearchForParents = whether to search a tx's vin for in-mempool parents, or
* look up parents from mapLinks. Must be true for entries not in the mempool
*/
- bool CalculateMemPoolAncestors(const CTxMemPoolEntry &entry, setEntries &setAncestors, uint64_t limitAncestorCount, uint64_t limitAncestorSize, uint64_t limitDescendantCount, uint64_t limitDescendantSize, std::string &errString, bool fSearchForParents = true) const;
+ bool CalculateMemPoolAncestors(const CTxMemPoolEntry& entry, setEntries& setAncestors, uint64_t limitAncestorCount, uint64_t limitAncestorSize, uint64_t limitDescendantCount, uint64_t limitDescendantSize, std::string& errString, bool fSearchForParents = true) const EXCLUSIVE_LOCKS_REQUIRED(cs);
/** Populate setDescendants with all in-mempool descendants of hash.
* Assumes that setDescendants includes all in-mempool descendants of anything
diff --git a/src/util.cpp b/src/util.cpp
index 2f81f50a71..238554ee4a 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -859,9 +859,13 @@ bool ArgsManager::ReadConfigStream(std::istream& stream, std::string& error, boo
}
// Check that the arg is known
- if (!IsArgKnown(strKey) && !ignore_invalid_keys) {
- error = strprintf("Invalid configuration value %s", option.first.c_str());
- return false;
+ if (!IsArgKnown(strKey)) {
+ if (!ignore_invalid_keys) {
+ error = strprintf("Invalid configuration value %s", option.first.c_str());
+ return false;
+ } else {
+ LogPrintf("Ignoring unknown configuration value %s\n", option.first);
+ }
}
}
return true;
diff --git a/src/validationinterface.h b/src/validationinterface.h
index 42cc2e9a20..bddc28d24a 100644
--- a/src/validationinterface.h
+++ b/src/validationinterface.h
@@ -53,6 +53,21 @@ void CallFunctionInValidationInterfaceQueue(std::function<void ()> func);
*/
void SyncWithValidationInterfaceQueue();
+/**
+ * Implement this to subscribe to events generated in validation
+ *
+ * Each CValidationInterface() subscriber will receive event callbacks
+ * in the order in which the events were generated by validation.
+ * Furthermore, each ValidationInterface() subscriber may assume that
+ * callbacks effectively run in a single thread with single-threaded
+ * memory consistency. That is, for a given ValidationInterface()
+ * instantiation, each callback will complete before the next one is
+ * invoked. This means, for example when a block is connected that the
+ * UpdatedBlockTip() callback may depend on an operation performed in
+ * the BlockConnected() callback without worrying about explicit
+ * synchronization. No ordering should be assumed across
+ * ValidationInterface() subscribers.
+ */
class CValidationInterface {
protected:
/**
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 4918100b30..218684fdf1 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -3018,7 +3018,8 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
size_t nLimitDescendants = gArgs.GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT);
size_t nLimitDescendantSize = gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT)*1000;
std::string errString;
- if (!mempool.CalculateMemPoolAncestors(entry, setAncestors, nLimitAncestors, nLimitAncestorSize, nLimitDescendants, nLimitDescendantSize, errString)) {
+ LOCK(::mempool.cs);
+ if (!::mempool.CalculateMemPoolAncestors(entry, setAncestors, nLimitAncestors, nLimitAncestorSize, nLimitDescendants, nLimitDescendantSize, errString)) {
strFailReason = _("Transaction has too long of a mempool chain");
return false;
}
@@ -4423,7 +4424,10 @@ std::vector<OutputGroup> CWallet::GroupOutputs(const std::vector<COutput>& outpu
size_t ancestors, descendants;
mempool.GetTransactionAncestry(output.tx->GetHash(), ancestors, descendants);
if (!single_coin && ExtractDestination(output.tx->tx->vout[output.i].scriptPubKey, dst)) {
- if (gmap.count(dst) == 10) {
+ // Limit output groups to no more than 10 entries, to protect
+ // against inadvertently creating a too-large transaction
+ // when using -avoidpartialspends
+ if (gmap[dst].m_outputs.size() >= 10) {
groups.push_back(gmap[dst]);
gmap.erase(dst);
}
diff --git a/test/functional/feature_includeconf.py b/test/functional/feature_includeconf.py
index 9a7a0ca103..d06f6826f0 100755
--- a/test/functional/feature_includeconf.py
+++ b/test/functional/feature_includeconf.py
@@ -55,9 +55,11 @@ class IncludeConfTest(BitcoinTestFramework):
self.stop_node(0, expected_stderr="warning: -includeconf cannot be used from included files; ignoring -includeconf=relative2.conf")
self.log.info("-includeconf cannot contain invalid arg")
- with open(os.path.join(self.options.tmpdir, "node0", "relative.conf"), "w", encoding="utf8") as f:
- f.write("foo=bar\n")
- self.nodes[0].assert_start_raises_init_error(expected_msg="Error reading configuration file: Invalid configuration value foo")
+
+ # Commented out as long as we ignore invalid arguments in configuration files
+ #with open(os.path.join(self.options.tmpdir, "node0", "relative.conf"), "w", encoding="utf8") as f:
+ # f.write("foo=bar\n")
+ #self.nodes[0].assert_start_raises_init_error(expected_msg="Error reading configuration file: Invalid configuration value foo")
self.log.info("-includeconf cannot be invalid path")
os.remove(os.path.join(self.options.tmpdir, "node0", "relative.conf"))
diff --git a/test/functional/rpc_scantxoutset.py b/test/functional/rpc_scantxoutset.py
index ce5d4da9e7..11c35b9f08 100755
--- a/test/functional/rpc_scantxoutset.py
+++ b/test/functional/rpc_scantxoutset.py
@@ -23,9 +23,25 @@ class ScantxoutsetTest(BitcoinTestFramework):
pubk2 = self.nodes[0].getaddressinfo(addr_LEGACY)['pubkey']
addr_BECH32 = self.nodes[0].getnewaddress("", "bech32")
pubk3 = self.nodes[0].getaddressinfo(addr_BECH32)['pubkey']
- self.nodes[0].sendtoaddress(addr_P2SH_SEGWIT, 1)
- self.nodes[0].sendtoaddress(addr_LEGACY, 2)
- self.nodes[0].sendtoaddress(addr_BECH32, 3)
+ self.nodes[0].sendtoaddress(addr_P2SH_SEGWIT, 0.001)
+ self.nodes[0].sendtoaddress(addr_LEGACY, 0.002)
+ self.nodes[0].sendtoaddress(addr_BECH32, 0.004)
+
+ #send to child keys of tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK
+ self.nodes[0].sendtoaddress("mkHV1C6JLheLoUSSZYk7x3FH5tnx9bu7yc", 0.008) # (m/0'/0'/0')
+ self.nodes[0].sendtoaddress("mipUSRmJAj2KrjSvsPQtnP8ynUon7FhpCR", 0.016) # (m/0'/0'/1')
+ self.nodes[0].sendtoaddress("n37dAGe6Mq1HGM9t4b6rFEEsDGq7Fcgfqg", 0.032) # (m/0'/0'/1500')
+ self.nodes[0].sendtoaddress("mqS9Rpg8nNLAzxFExsgFLCnzHBsoQ3PRM6", 0.064) # (m/0'/0'/0)
+ self.nodes[0].sendtoaddress("mnTg5gVWr3rbhHaKjJv7EEEc76ZqHgSj4S", 0.128) # (m/0'/0'/1)
+ self.nodes[0].sendtoaddress("mketCd6B9U9Uee1iCsppDJJBHfvi6U6ukC", 0.256) # (m/0'/0'/1500)
+ self.nodes[0].sendtoaddress("mj8zFzrbBcdaWXowCQ1oPZ4qioBVzLzAp7", 0.512) # (m/1/1/0')
+ self.nodes[0].sendtoaddress("mfnKpKQEftniaoE1iXuMMePQU3PUpcNisA", 1.024) # (m/1/1/1')
+ self.nodes[0].sendtoaddress("mou6cB1kaP1nNJM1sryW6YRwnd4shTbXYQ", 2.048) # (m/1/1/1500')
+ self.nodes[0].sendtoaddress("mtfUoUax9L4tzXARpw1oTGxWyoogp52KhJ", 4.096) # (m/1/1/0)
+ self.nodes[0].sendtoaddress("mxp7w7j8S1Aq6L8StS2PqVvtt4HGxXEvdy", 8.192) # (m/1/1/1)
+ self.nodes[0].sendtoaddress("mpQ8rokAhp1TAtJQR6F6TaUmjAWkAWYYBq", 16.384) # (m/1/1/1500)
+
+
self.nodes[0].generate(1)
self.log.info("Stop node, remove wallet, mine again some blocks...")
@@ -36,13 +52,39 @@ class ScantxoutsetTest(BitcoinTestFramework):
self.restart_node(0, ['-nowallet'])
self.log.info("Test if we have found the non HD unspent outputs.")
- assert_equal(self.nodes[0].scantxoutset("start", [ {"pubkey": {"pubkey": pubk1}}, {"pubkey": {"pubkey": pubk2}}, {"pubkey": {"pubkey": pubk3}}])['total_amount'], 6)
- assert_equal(self.nodes[0].scantxoutset("start", [ {"address": addr_P2SH_SEGWIT}, {"address": addr_LEGACY}, {"address": addr_BECH32}])['total_amount'], 6)
- assert_equal(self.nodes[0].scantxoutset("start", [ {"address": addr_P2SH_SEGWIT}, {"address": addr_LEGACY}, {"pubkey": {"pubkey": pubk3}} ])['total_amount'], 6)
+ assert_equal(self.nodes[0].scantxoutset("start", [ "pkh(" + pubk1 + ")", "pkh(" + pubk2 + ")", "pkh(" + pubk3 + ")"])['total_amount'], Decimal("0.002"))
+ assert_equal(self.nodes[0].scantxoutset("start", [ "wpkh(" + pubk1 + ")", "wpkh(" + pubk2 + ")", "wpkh(" + pubk3 + ")"])['total_amount'], Decimal("0.004"))
+ assert_equal(self.nodes[0].scantxoutset("start", [ "sh(wpkh(" + pubk1 + "))", "sh(wpkh(" + pubk2 + "))", "sh(wpkh(" + pubk3 + "))"])['total_amount'], Decimal("0.001"))
+ assert_equal(self.nodes[0].scantxoutset("start", [ "combo(" + pubk1 + ")", "combo(" + pubk2 + ")", "combo(" + pubk3 + ")"])['total_amount'], Decimal("0.007"))
+ assert_equal(self.nodes[0].scantxoutset("start", [ "addr(" + addr_P2SH_SEGWIT + ")", "addr(" + addr_LEGACY + ")", "addr(" + addr_BECH32 + ")"])['total_amount'], Decimal("0.007"))
+ assert_equal(self.nodes[0].scantxoutset("start", [ "addr(" + addr_P2SH_SEGWIT + ")", "addr(" + addr_LEGACY + ")", "combo(" + pubk3 + ")"])['total_amount'], Decimal("0.007"))
- self.log.info("Test invalid parameters.")
- assert_raises_rpc_error(-8, 'Scanobject "pubkey" must contain an object as value', self.nodes[0].scantxoutset, "start", [ {"pubkey": pubk1}]) #missing pubkey object
- assert_raises_rpc_error(-8, 'Scanobject "address" must contain a single string as value', self.nodes[0].scantxoutset, "start", [ {"address": {"address": addr_P2SH_SEGWIT}}]) #invalid object for address object
+ self.log.info("Test extended key derivation.")
+ assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0h/0h)"])['total_amount'], Decimal("0.008"))
+ assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0'/1h)"])['total_amount'], Decimal("0.016"))
+ assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0h/0'/1500')"])['total_amount'], Decimal("0.032"))
+ assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0h/0h/0)"])['total_amount'], Decimal("0.064"))
+ assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0h/1)"])['total_amount'], Decimal("0.128"))
+ assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0h/0'/1500)"])['total_amount'], Decimal("0.256"))
+ assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0h/*h)", "range": 1499}])['total_amount'], Decimal("0.024"))
+ assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0'/*h)", "range": 1500}])['total_amount'], Decimal("0.056"))
+ assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0h/0'/*)", "range": 1499}])['total_amount'], Decimal("0.192"))
+ assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0h/*)", "range": 1500}])['total_amount'], Decimal("0.448"))
+ assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/0')"])['total_amount'], Decimal("0.512"))
+ assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/1')"])['total_amount'], Decimal("1.024"))
+ assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/1500h)"])['total_amount'], Decimal("2.048"))
+ assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/0)"])['total_amount'], Decimal("4.096"))
+ assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/1)"])['total_amount'], Decimal("8.192"))
+ assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/1500)"])['total_amount'], Decimal("16.384"))
+ assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/0)"])['total_amount'], Decimal("4.096"))
+ assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/1)"])['total_amount'], Decimal("8.192"))
+ assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/1500)"])['total_amount'], Decimal("16.384"))
+ assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*')", "range": 1499}])['total_amount'], Decimal("1.536"))
+ assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*')", "range": 1500}])['total_amount'], Decimal("3.584"))
+ assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)", "range": 1499}])['total_amount'], Decimal("12.288"))
+ assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)", "range": 1500}])['total_amount'], Decimal("28.672"))
+ assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/*)", "range": 1499}])['total_amount'], Decimal("12.288"))
+ assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/*)", "range": 1500}])['total_amount'], Decimal("28.672"))
if __name__ == '__main__':
ScantxoutsetTest().main()
diff --git a/test/functional/wallet_groups.py b/test/functional/wallet_groups.py
index 0d27815da0..408e9dfef0 100755
--- a/test/functional/wallet_groups.py
+++ b/test/functional/wallet_groups.py
@@ -5,6 +5,8 @@
"""Test wallet group functionality."""
from test_framework.test_framework import BitcoinTestFramework
+from test_framework.mininode import FromHex, ToHex
+from test_framework.messages import CTransaction
from test_framework.util import (
assert_equal,
)
@@ -63,5 +65,29 @@ class WalletGroupTest(BitcoinTestFramework):
assert_approx(v[0], 0.2)
assert_approx(v[1], 1.3, 0.0001)
+ # Empty out node2's wallet
+ self.nodes[2].sendtoaddress(address=self.nodes[0].getnewaddress(), amount=self.nodes[2].getbalance(), subtractfeefromamount=True)
+ self.sync_all()
+ self.nodes[0].generate(1)
+
+ # Fill node2's wallet with 10000 outputs corresponding to the same
+ # scriptPubKey
+ for i in range(5):
+ raw_tx = self.nodes[0].createrawtransaction([{"txid":"0"*64, "vout":0}], [{addr2[0]: 0.05}])
+ tx = FromHex(CTransaction(), raw_tx)
+ tx.vin = []
+ tx.vout = [tx.vout[0]] * 2000
+ funded_tx = self.nodes[0].fundrawtransaction(ToHex(tx))
+ signed_tx = self.nodes[0].signrawtransactionwithwallet(funded_tx['hex'])
+ self.nodes[0].sendrawtransaction(signed_tx['hex'])
+ self.nodes[0].generate(1)
+
+ self.sync_all()
+
+ # Check that we can create a transaction that only requires ~100 of our
+ # utxos, without pulling in all outputs and creating a transaction that
+ # is way too big.
+ assert self.nodes[2].sendtoaddress(address=addr2[0], amount=5)
+
if __name__ == '__main__':
WalletGroupTest().main ()