aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml7
-rw-r--r--Makefile.am3
-rw-r--r--build_msvc/vcpkg.json8
-rwxr-xr-xci/test/05_before_script.sh2
-rw-r--r--contrib/guix/manifest.scm7
-rw-r--r--contrib/guix/patches/gcc-broken-longjmp.patch68
-rwxr-xr-xcontrib/seeds/makeseeds.py90
-rw-r--r--contrib/seeds/suspicious_hosts.txt16
-rw-r--r--contrib/testgen/README.md2
-rwxr-xr-xcontrib/testgen/gen_key_io_test_vectors.py22
-rw-r--r--depends/Makefile2
-rw-r--r--depends/README.md5
-rw-r--r--depends/funcs.mk22
-rw-r--r--doc/REST-interface.md18
-rw-r--r--doc/release-process.md3
-rw-r--r--src/Makefile.bench.include1
-rw-r--r--src/arith_uint256.cpp29
-rw-r--r--src/arith_uint256.h2
-rw-r--r--src/bench/wallet_loading.cpp83
-rw-r--r--src/bitcoin-cli.cpp4
-rw-r--r--src/init.cpp3
-rw-r--r--src/logging/timer.h8
-rw-r--r--src/netbase.cpp28
-rw-r--r--src/netbase.h4
-rw-r--r--src/qt/bitcoin.cpp2
-rw-r--r--src/qt/bitcoinamountfield.cpp22
-rw-r--r--src/qt/bitcoinamountfield.h3
-rw-r--r--src/qt/bitcoingui.cpp13
-rw-r--r--src/qt/bitcoingui.h5
-rw-r--r--src/qt/bitcoinunits.cpp172
-rw-r--r--src/qt/bitcoinunits.h34
-rw-r--r--src/qt/coincontroldialog.cpp4
-rw-r--r--src/qt/guiutil.cpp5
-rw-r--r--src/qt/optionsmodel.cpp31
-rw-r--r--src/qt/optionsmodel.h13
-rw-r--r--src/qt/overviewpage.cpp10
-rw-r--r--src/qt/psbtoperationsdialog.cpp4
-rw-r--r--src/qt/sendcoinsdialog.cpp3
-rw-r--r--src/qt/test/wallettests.cpp15
-rw-r--r--src/qt/transactiondesc.cpp28
-rw-r--r--src/qt/transactiondesc.h6
-rw-r--r--src/qt/transactionrecord.h21
-rw-r--r--src/qt/transactiontablemodel.cpp3
-rw-r--r--src/qt/walletview.h3
-rw-r--r--src/random.cpp2
-rw-r--r--src/sync.h4
-rw-r--r--src/test/data/key_io_invalid.json136
-rw-r--r--src/test/data/key_io_valid.json280
-rw-r--r--src/test/util/logging.h2
-rw-r--r--src/test/util/setup_common.cpp7
-rw-r--r--src/txmempool.cpp2
-rw-r--r--src/util/epochguard.h3
-rw-r--r--src/util/macros.h2
-rw-r--r--src/wallet/rpc/wallet.cpp2
-rw-r--r--src/wallet/wallet.cpp14
-rw-r--r--test/README.md6
-rw-r--r--test/config.ini.in1
-rw-r--r--test/functional/README.md2
-rwxr-xr-xtest/functional/test_framework/test_framework.py15
-rwxr-xr-xtest/functional/test_runner.py2
-rwxr-xr-xtest/functional/tool_signet_miner.py62
-rwxr-xr-xtest/functional/wallet_avoidreuse.py11
-rwxr-xr-xtest/functional/wallet_createwallet.py5
-rwxr-xr-xtest/lint/lint-git-commit-check.py63
-rwxr-xr-xtest/lint/lint-git-commit-check.sh48
-rwxr-xr-xtest/lint/lint-logs.py34
-rwxr-xr-xtest/lint/lint-logs.sh28
-rwxr-xr-xtest/lint/lint-python.py131
-rwxr-xr-xtest/lint/lint-python.sh111
-rwxr-xr-xtest/lint/lint-whitespace.py135
-rwxr-xr-xtest/lint/lint-whitespace.sh115
71 files changed, 1184 insertions, 873 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index 5bfdcbc9b1..c4aae3a50a 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -96,7 +96,7 @@ task:
env:
PATH: 'C:\jom;C:\Python39;C:\Python39\Scripts;C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin;%PATH%'
PYTHONUTF8: 1
- CI_VCPKG_TAG: '2022.02.23'
+ CI_VCPKG_TAG: '2022.04.12'
VCPKG_DOWNLOADS: 'C:\Users\ContainerAdministrator\AppData\Local\vcpkg\downloads'
VCPKG_DEFAULT_BINARY_CACHE: 'C:\Users\ContainerAdministrator\AppData\Local\vcpkg\archives'
CCACHE_DIR: 'C:\Users\ContainerAdministrator\AppData\Local\ccache'
@@ -106,6 +106,7 @@ task:
QT_SOURCE_DIR: 'C:\qt-everywhere-src-5.15.3'
QTBASEDIR: 'C:\Qt_static'
x64_NATIVE_TOOLS: '"C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvars64.bat"'
+ QT_CONFIGURE_COMMAND: '..\configure -release -silent -opensource -confirm-license -opengl desktop -static -static-runtime -mp -qt-zlib -qt-pcre -qt-libpng -nomake examples -nomake tests -nomake tools -no-angle -no-dbus -no-gif -no-gtk -no-ico -no-icu -no-libjpeg -no-libudev -no-sql-sqlite -no-sql-odbc -no-sqlite -no-vulkan -skip qt3d -skip qtactiveqt -skip qtandroidextras -skip qtcharts -skip qtconnectivity -skip qtdatavis3d -skip qtdeclarative -skip doc -skip qtdoc -skip qtgamepad -skip qtgraphicaleffects -skip qtimageformats -skip qtlocation -skip qtlottie -skip qtmacextras -skip qtmultimedia -skip qtnetworkauth -skip qtpurchasing -skip qtquick3d -skip qtquickcontrols -skip qtquickcontrols2 -skip qtquicktimeline -skip qtremoteobjects -skip qtscript -skip qtscxml -skip qtsensors -skip qtserialbus -skip qtserialport -skip qtspeech -skip qtsvg -skip qtvirtualkeyboard -skip qtwayland -skip qtwebchannel -skip qtwebengine -skip qtwebglplugin -skip qtwebsockets -skip qtwebview -skip qtx11extras -skip qtxmlpatterns -no-openssl -no-feature-bearermanagement -no-feature-printdialog -no-feature-printer -no-feature-printpreviewdialog -no-feature-printpreviewwidget -no-feature-sql -no-feature-sqlmodel -no-feature-textbrowser -no-feature-textmarkdownwriter -no-feature-textodfwriter -no-feature-xml'
IgnoreWarnIntDirInTempDetected: 'true'
merge_script:
- git config --global user.email "ci@ci.ci"
@@ -120,7 +121,7 @@ task:
folder: "%QTBASEDIR%"
reupload_on_changes: false
fingerprint_script:
- - echo %QT_DOWNLOAD_URL%
+ - echo %QT_DOWNLOAD_URL% %QT_CONFIGURE_COMMAND%
- msbuild -version
populate_script:
- curl -L -o C:\jom.zip http://download.qt.io/official_releases/jom/jom.zip
@@ -132,7 +133,7 @@ task:
- cd %QT_SOURCE_DIR%
- mkdir build
- cd build
- - ..\configure -release -silent -opensource -confirm-license -opengl desktop -static -static-runtime -mp -qt-zlib -qt-pcre -qt-libpng -nomake examples -nomake tests -nomake tools -no-angle -no-dbus -no-gif -no-gtk -no-ico -no-icu -no-libjpeg -no-libudev -no-sql-sqlite -no-sql-odbc -no-sqlite -no-vulkan -skip qt3d -skip qtactiveqt -skip qtandroidextras -skip qtcharts -skip qtconnectivity -skip qtdatavis3d -skip qtdeclarative -skip doc -skip qtdoc -skip qtgamepad -skip qtgraphicaleffects -skip qtimageformats -skip qtlocation -skip qtlottie -skip qtmacextras -skip qtmultimedia -skip qtnetworkauth -skip qtpurchasing -skip qtquick3d -skip qtquickcontrols -skip qtquickcontrols2 -skip qtquicktimeline -skip qtremoteobjects -skip qtscript -skip qtscxml -skip qtsensors -skip qtserialbus -skip qtserialport -skip qtspeech -skip qtsvg -skip qtvirtualkeyboard -skip qtwayland -skip qtwebchannel -skip qtwebengine -skip qtwebglplugin -skip qtwebsockets -skip qtwebview -skip qtx11extras -skip qtxmlpatterns -no-openssl -no-feature-bearermanagement -no-feature-printdialog -no-feature-printer -no-feature-printpreviewdialog -no-feature-printpreviewwidget -no-feature-sql -no-feature-sqlmodel -no-feature-textbrowser -no-feature-textmarkdownwriter -no-feature-textodfwriter -no-feature-xml -prefix %QTBASEDIR%
+ - '%QT_CONFIGURE_COMMAND% -prefix %QTBASEDIR%'
- jom
- jom install
vcpkg_tools_cache:
diff --git a/Makefile.am b/Makefile.am
index 54e9a6865f..60167e3b7e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -47,7 +47,8 @@ DIST_CONTRIB = \
$(top_srcdir)/test/sanitizer_suppressions/tsan \
$(top_srcdir)/test/sanitizer_suppressions/ubsan \
$(top_srcdir)/contrib/linearize/linearize-data.py \
- $(top_srcdir)/contrib/linearize/linearize-hashes.py
+ $(top_srcdir)/contrib/linearize/linearize-hashes.py \
+ $(top_srcdir)/contrib/signet/miner
DIST_SHARE = \
$(top_srcdir)/share/genbuild.sh \
diff --git a/build_msvc/vcpkg.json b/build_msvc/vcpkg.json
index 48b4d1fd20..86773d1fd3 100644
--- a/build_msvc/vcpkg.json
+++ b/build_msvc/vcpkg.json
@@ -13,13 +13,5 @@
"features": ["thread"]
},
"zeromq"
- ],
- "builtin-baseline": "b86c0c35b88e2bf3557ff49dc831689c2f085090",
- "overrides": [
- {
- "name": "zeromq",
- "version": "4.3.4",
- "port-version": 3
- }
]
}
diff --git a/ci/test/05_before_script.sh b/ci/test/05_before_script.sh
index d8dcb708aa..fc2f76797c 100755
--- a/ci/test/05_before_script.sh
+++ b/ci/test/05_before_script.sh
@@ -45,7 +45,7 @@ if [ -z "$NO_DEPENDS" ]; then
else
SHELL_OPTS="CONFIG_SHELL="
fi
- CI_EXEC "$SHELL_OPTS" make "$MAKEJOBS" -C depends HOST="$HOST" "$DEP_OPTS"
+ CI_EXEC "$SHELL_OPTS" make "$MAKEJOBS" -C depends HOST="$HOST" "$DEP_OPTS" LOG=1
fi
if [ -n "$PREVIOUS_RELEASES_TO_DOWNLOAD" ]; then
CI_EXEC test/get_previous_releases.py -b -t "$PREVIOUS_RELEASES_DIR" "${PREVIOUS_RELEASES_TO_DOWNLOAD}"
diff --git a/contrib/guix/manifest.scm b/contrib/guix/manifest.scm
index fcec592c2c..708d2e698d 100644
--- a/contrib/guix/manifest.scm
+++ b/contrib/guix/manifest.scm
@@ -162,9 +162,10 @@ desirable for building Bitcoin Core release binaries."
(define (make-gcc-with-pthreads gcc)
(package-with-extra-configure-variable gcc "--enable-threads" "posix"))
-(define (make-mingw-w64-cross-gcc-vmov-alignment cross-gcc)
+(define (make-mingw-w64-cross-gcc cross-gcc)
(package-with-extra-patches cross-gcc
- (search-our-patches "vmov-alignment.patch")))
+ (search-our-patches "vmov-alignment.patch"
+ "gcc-broken-longjmp.patch")))
(define (make-mingw-pthreads-cross-toolchain target)
"Create a cross-compilation toolchain package for TARGET"
@@ -172,7 +173,7 @@ desirable for building Bitcoin Core release binaries."
(pthreads-xlibc mingw-w64-x86_64-winpthreads)
(pthreads-xgcc (make-gcc-with-pthreads
(cross-gcc target
- #:xgcc (make-ssp-fixed-gcc (make-mingw-w64-cross-gcc-vmov-alignment base-gcc))
+ #:xgcc (make-ssp-fixed-gcc (make-mingw-w64-cross-gcc base-gcc))
#:xbinutils xbinutils
#:libc pthreads-xlibc))))
;; Define a meta-package that propagates the resulting XBINUTILS, XLIBC, and
diff --git a/contrib/guix/patches/gcc-broken-longjmp.patch b/contrib/guix/patches/gcc-broken-longjmp.patch
new file mode 100644
index 0000000000..1cfc0918b0
--- /dev/null
+++ b/contrib/guix/patches/gcc-broken-longjmp.patch
@@ -0,0 +1,68 @@
+commit eb5698897c52702498938592d7f76e67d126451f
+Author: Eric Botcazou <ebotcazou@adacore.com>
+Date: Wed May 5 22:48:51 2021 +0200
+
+ Fix PR target/100402
+
+ This is a regression for 64-bit Windows present from mainline down to the 9
+ branch and introduced by the fix for PR target/99234. Again SEH, but with
+ a twist related to the way MinGW implements setjmp/longjmp, which turns out
+ to be piggybacked on SEH with recent versions of MinGW, i.e. the longjmp
+ performs a bona-fide unwinding of the stack, because it calls RtlUnwindEx
+ with the second argument initially passed to setjmp, which is the result of
+ __builtin_frame_address (0) in the MinGW header file:
+
+ define setjmp(BUF) _setjmp((BUF), __builtin_frame_address (0))
+
+ This means that we directly expose the frame pointer to the SEH machinery
+ here (unlike with regular exception handling where we use an intermediate
+ CFA) and thus that we cannot do whatever we want with it. The old code
+ would leave it unaligned, i.e. not multiple of 16, whereas the new code
+ aligns it, but this breaks for some reason; at least it appears that a
+ .seh_setframe directive with 0 as second argument always works, so the
+ fix aligns it this way.
+
+ gcc/
+ PR target/100402
+ * config/i386/i386.c (ix86_compute_frame_layout): For a SEH target,
+ always return the establisher frame for __builtin_frame_address (0).
+ gcc/testsuite/
+ * gcc.c-torture/execute/20210505-1.c: New test.
+
+diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
+index 2f838840e96..06ad1b2274e 100644
+--- a/gcc/config/i386/i386.c
++++ b/gcc/config/i386/i386.c
+@@ -6356,12 +6356,29 @@ ix86_compute_frame_layout (void)
+ area, see the SEH code in config/i386/winnt.c for the rationale. */
+ frame->hard_frame_pointer_offset = frame->sse_reg_save_offset;
+
+- /* If we can leave the frame pointer where it is, do so. Also, return
++ /* If we can leave the frame pointer where it is, do so; however return
+ the establisher frame for __builtin_frame_address (0) or else if the
+- frame overflows the SEH maximum frame size. */
++ frame overflows the SEH maximum frame size.
++
++ Note that the value returned by __builtin_frame_address (0) is quite
++ constrained, because setjmp is piggybacked on the SEH machinery with
++ recent versions of MinGW:
++
++ # elif defined(__SEH__)
++ # if defined(__aarch64__) || defined(_ARM64_)
++ # define setjmp(BUF) _setjmp((BUF), __builtin_sponentry())
++ # elif (__MINGW_GCC_VERSION < 40702)
++ # define setjmp(BUF) _setjmp((BUF), mingw_getsp())
++ # else
++ # define setjmp(BUF) _setjmp((BUF), __builtin_frame_address (0))
++ # endif
++
++ and the second argument passed to _setjmp, if not null, is forwarded
++ to the TargetFrame parameter of RtlUnwindEx by longjmp (after it has
++ built an ExceptionRecord on the fly describing the setjmp buffer). */
+ const HOST_WIDE_INT diff
+ = frame->stack_pointer_offset - frame->hard_frame_pointer_offset;
+- if (diff <= 255)
++ if (diff <= 255 && !crtl->accesses_prior_frames)
+ {
+ /* The resulting diff will be a multiple of 16 lower than 255,
+ i.e. at most 240 as required by the unwind data structure. */
diff --git a/contrib/seeds/makeseeds.py b/contrib/seeds/makeseeds.py
index 2b377f6c01..78eb04a836 100755
--- a/contrib/seeds/makeseeds.py
+++ b/contrib/seeds/makeseeds.py
@@ -10,18 +10,16 @@ import re
import sys
import dns.resolver
import collections
+from typing import List, Dict, Union
NSEEDS=512
-MAX_SEEDS_PER_ASN=2
-
-MIN_BLOCKS = 337600
-
-# These are hosts that have been observed to be behaving strangely (e.g.
-# aggressively connecting to every node).
-with open("suspicious_hosts.txt", mode="r", encoding="utf-8") as f:
- SUSPICIOUS_HOSTS = {s.strip() for s in f if s.strip()}
+MAX_SEEDS_PER_ASN = {
+ 'ipv4': 2,
+ 'ipv6': 10,
+}
+MIN_BLOCKS = 730000
PATTERN_IPV4 = re.compile(r"^((\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})):(\d+)$")
PATTERN_IPV6 = re.compile(r"^\[([0-9a-z:]+)\]:(\d+)$")
@@ -40,9 +38,13 @@ PATTERN_AGENT = re.compile(
r"23.99"
r")")
-def parseline(line):
+def parseline(line: str) -> Union[dict, None]:
+ """ Parses a line from `seeds_main.txt` into a dictionary of details for that line.
+ or `None`, if the line could not be parsed.
+ """
sline = line.split()
if len(sline) < 11:
+ # line too short to be valid, skip it.
return None
m = PATTERN_IPV4.match(sline[0])
sortkey = None
@@ -107,25 +109,26 @@ def parseline(line):
'sortkey': sortkey,
}
-def dedup(ips):
- '''deduplicate by address,port'''
+def dedup(ips: List[Dict]) -> List[Dict]:
+ """ Remove duplicates from `ips` where multiple ips share address and port. """
d = {}
for ip in ips:
d[ip['ip'],ip['port']] = ip
return list(d.values())
-def filtermultiport(ips):
- '''Filter out hosts with more nodes per IP'''
+def filtermultiport(ips: List[Dict]) -> List[Dict]:
+ """ Filter out hosts with more nodes per IP"""
hist = collections.defaultdict(list)
for ip in ips:
hist[ip['sortkey']].append(ip)
return [value[0] for (key,value) in list(hist.items()) if len(value)==1]
-def lookup_asn(net, ip):
- '''
- Look up the asn for an IP (4 or 6) address by querying cymru.com, or None
- if it could not be found.
- '''
+def lookup_asn(net: str, ip: str) -> Union[int, None]:
+ """ Look up the asn for an `ip` address by querying cymru.com
+ on network `net` (e.g. ipv4 or ipv6).
+
+ Returns in integer ASN or None if it could not be found.
+ """
try:
if net == 'ipv4':
ipaddr = ip
@@ -147,20 +150,33 @@ def lookup_asn(net, ip):
return None
# Based on Greg Maxwell's seed_filter.py
-def filterbyasn(ips, max_per_asn, max_per_net):
+def filterbyasn(ips: List[Dict], max_per_asn: Dict, max_per_net: int) -> List[Dict]:
+ """ Prunes `ips` by
+ (a) trimming ips to have at most `max_per_net` ips from each net (e.g. ipv4, ipv6); and
+ (b) trimming ips to have at most `max_per_asn` ips from each asn in each net.
+ """
# Sift out ips by type
ips_ipv46 = [ip for ip in ips if ip['net'] in ['ipv4', 'ipv6']]
ips_onion = [ip for ip in ips if ip['net'] == 'onion']
# Filter IPv46 by ASN, and limit to max_per_net per network
result = []
- net_count = collections.defaultdict(int)
- asn_count = collections.defaultdict(int)
- for ip in ips_ipv46:
+ net_count: Dict[str, int] = collections.defaultdict(int)
+ asn_count: Dict[int, int] = collections.defaultdict(int)
+
+ for i, ip in enumerate(ips_ipv46):
+ if i % 10 == 0:
+ # give progress update
+ print(f"{i:6d}/{len(ips_ipv46)} [{100*i/len(ips_ipv46):04.1f}%]\r", file=sys.stderr, end='', flush=True)
+
if net_count[ip['net']] == max_per_net:
+ # do not add this ip as we already too many
+ # ips from this network
continue
asn = lookup_asn(ip['net'], ip['ip'])
- if asn is None or asn_count[asn] == max_per_asn:
+ if asn is None or asn_count[asn] == max_per_asn[ip['net']]:
+ # do not add this ip as we already have too many
+ # ips from this ASN on this network
continue
asn_count[asn] += 1
net_count[ip['net']] += 1
@@ -170,35 +186,33 @@ def filterbyasn(ips, max_per_asn, max_per_net):
result.extend(ips_onion[0:max_per_net])
return result
-def ip_stats(ips):
- hist = collections.defaultdict(int)
+def ip_stats(ips: List[Dict]) -> str:
+ """ Format and return pretty string from `ips`. """
+ hist: Dict[str, int] = collections.defaultdict(int)
for ip in ips:
if ip is not None:
hist[ip['net']] += 1
- return '%6d %6d %6d' % (hist['ipv4'], hist['ipv6'], hist['onion'])
+ return f"{hist['ipv4']:6d} {hist['ipv6']:6d} {hist['onion']:6d}"
def main():
lines = sys.stdin.readlines()
ips = [parseline(line) for line in lines]
print('\x1b[7m IPv4 IPv6 Onion Pass \x1b[0m', file=sys.stderr)
- print('%s Initial' % (ip_stats(ips)), file=sys.stderr)
+ print(f'{ip_stats(ips):s} Initial', file=sys.stderr)
# Skip entries with invalid address.
ips = [ip for ip in ips if ip is not None]
- print('%s Skip entries with invalid address' % (ip_stats(ips)), file=sys.stderr)
+ print(f'{ip_stats(ips):s} Skip entries with invalid address', file=sys.stderr)
# Skip duplicates (in case multiple seeds files were concatenated)
ips = dedup(ips)
- print('%s After removing duplicates' % (ip_stats(ips)), file=sys.stderr)
- # Skip entries from suspicious hosts.
- ips = [ip for ip in ips if ip['ip'] not in SUSPICIOUS_HOSTS]
- print('%s Skip entries from suspicious hosts' % (ip_stats(ips)), file=sys.stderr)
+ print(f'{ip_stats(ips):s} After removing duplicates', file=sys.stderr)
# Enforce minimal number of blocks.
ips = [ip for ip in ips if ip['blocks'] >= MIN_BLOCKS]
- print('%s Enforce minimal number of blocks' % (ip_stats(ips)), file=sys.stderr)
+ print(f'{ip_stats(ips):s} Enforce minimal number of blocks', file=sys.stderr)
# Require service bit 1.
ips = [ip for ip in ips if (ip['service'] & 1) == 1]
- print('%s Require service bit 1' % (ip_stats(ips)), file=sys.stderr)
+ print(f'{ip_stats(ips):s} Require service bit 1', file=sys.stderr)
# Require at least 50% 30-day uptime for clearnet, 10% for onion.
req_uptime = {
'ipv4': 50,
@@ -206,18 +220,18 @@ def main():
'onion': 10,
}
ips = [ip for ip in ips if ip['uptime'] > req_uptime[ip['net']]]
- print('%s Require minimum uptime' % (ip_stats(ips)), file=sys.stderr)
+ print(f'{ip_stats(ips):s} Require minimum uptime', file=sys.stderr)
# Require a known and recent user agent.
ips = [ip for ip in ips if PATTERN_AGENT.match(ip['agent'])]
- print('%s Require a known and recent user agent' % (ip_stats(ips)), file=sys.stderr)
+ print(f'{ip_stats(ips):s} Require a known and recent user agent', file=sys.stderr)
# Sort by availability (and use last success as tie breaker)
ips.sort(key=lambda x: (x['uptime'], x['lastsuccess'], x['ip']), reverse=True)
# Filter out hosts with multiple bitcoin ports, these are likely abusive
ips = filtermultiport(ips)
- print('%s Filter out hosts with multiple bitcoin ports' % (ip_stats(ips)), file=sys.stderr)
+ print(f'{ip_stats(ips):s} Filter out hosts with multiple bitcoin ports', file=sys.stderr)
# Look up ASNs and limit results, both per ASN and globally.
ips = filterbyasn(ips, MAX_SEEDS_PER_ASN, NSEEDS)
- print('%s Look up ASNs and limit results per ASN and per net' % (ip_stats(ips)), file=sys.stderr)
+ print(f'{ip_stats(ips):s} Look up ASNs and limit results per ASN and per net', file=sys.stderr)
# Sort the results by IP address (for deterministic output).
ips.sort(key=lambda x: (x['net'], x['sortkey']))
for ip in ips:
diff --git a/contrib/seeds/suspicious_hosts.txt b/contrib/seeds/suspicious_hosts.txt
deleted file mode 100644
index 13385cc816..0000000000
--- a/contrib/seeds/suspicious_hosts.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-130.211.129.106
-148.251.238.178
-176.9.46.6
-178.63.107.226
-54.173.72.127
-54.174.10.182
-54.183.64.54
-54.194.231.211
-54.66.214.167
-54.66.220.137
-54.67.33.14
-54.77.251.214
-54.94.195.96
-54.94.200.247
-83.81.130.26
-88.198.17.7 \ No newline at end of file
diff --git a/contrib/testgen/README.md b/contrib/testgen/README.md
index 66276ec9dd..2f0288df16 100644
--- a/contrib/testgen/README.md
+++ b/contrib/testgen/README.md
@@ -2,7 +2,7 @@
Utilities to generate test vectors for the data-driven Bitcoin tests.
-Usage:
+To use inside a scripted-diff (or just execute directly):
./gen_key_io_test_vectors.py valid 70 > ../../src/test/data/key_io_valid.json
./gen_key_io_test_vectors.py invalid 70 > ../../src/test/data/key_io_invalid.json
diff --git a/contrib/testgen/gen_key_io_test_vectors.py b/contrib/testgen/gen_key_io_test_vectors.py
index 4aa7dc200b..7bfb1d76a8 100755
--- a/contrib/testgen/gen_key_io_test_vectors.py
+++ b/contrib/testgen/gen_key_io_test_vectors.py
@@ -4,10 +4,6 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
'''
Generate valid and invalid base58/bech32(m) address and private key test vectors.
-
-Usage:
- ./gen_key_io_test_vectors.py valid 70 > ../../src/test/data/key_io_valid.json
- ./gen_key_io_test_vectors.py invalid 70 > ../../src/test/data/key_io_invalid.json
'''
from itertools import islice
@@ -131,7 +127,7 @@ def is_valid_bech32(v):
def gen_valid_base58_vector(template):
'''Generate valid base58 vector'''
prefix = bytearray(template[0])
- payload = bytearray(os.urandom(template[1]))
+ payload = rand_bytes(size=template[1])
suffix = bytearray(template[2])
dst_prefix = bytearray(template[4])
dst_suffix = bytearray(template[5])
@@ -143,7 +139,7 @@ def gen_valid_bech32_vector(template):
'''Generate valid bech32 vector'''
hrp = template[0]
witver = template[1]
- witprog = bytearray(os.urandom(template[2]))
+ witprog = rand_bytes(size=template[2])
encoding = template[4]
dst_prefix = bytearray(template[5])
rv = bech32_encode(encoding, hrp, [witver] + convertbits(witprog, 8, 5))
@@ -173,17 +169,17 @@ def gen_invalid_base58_vector(template):
corrupt_suffix = randbool(0.2)
if corrupt_prefix:
- prefix = os.urandom(1)
+ prefix = rand_bytes(size=1)
else:
prefix = bytearray(template[0])
if randomize_payload_size:
- payload = os.urandom(max(int(random.expovariate(0.5)), 50))
+ payload = rand_bytes(size=max(int(random.expovariate(0.5)), 50))
else:
- payload = os.urandom(template[1])
+ payload = rand_bytes(size=template[1])
if corrupt_suffix:
- suffix = os.urandom(len(template[2]))
+ suffix = rand_bytes(size=len(template[2]))
else:
suffix = bytearray(template[2])
@@ -204,7 +200,7 @@ def gen_invalid_bech32_vector(template):
to_upper = randbool(0.1)
hrp = template[0]
witver = template[1]
- witprog = bytearray(os.urandom(template[2]))
+ witprog = rand_bytes(size=template[2])
encoding = template[3]
if no_data:
@@ -234,6 +230,9 @@ def randbool(p = 0.5):
'''Return True with P(p)'''
return random.random() < p
+def rand_bytes(*, size):
+ return bytearray(random.getrandbits(8) for _ in range(size))
+
def gen_invalid_vectors():
'''Generate invalid test vectors'''
# start with some manual edge-cases
@@ -250,6 +249,7 @@ def gen_invalid_vectors():
if __name__ == '__main__':
import json
iters = {'valid':gen_valid_vectors, 'invalid':gen_invalid_vectors}
+ random.seed(42)
try:
uiter = iters[sys.argv[1]]
except IndexError:
diff --git a/depends/Makefile b/depends/Makefile
index 723509c81d..b901533786 100644
--- a/depends/Makefile
+++ b/depends/Makefile
@@ -271,7 +271,7 @@ clean-all: clean
@rm -rf $(SOURCES_PATH) x86_64* i686* mips* arm* aarch64* powerpc* riscv32* riscv64* s390x*
clean:
- @rm -rf $(WORK_PATH) $(BASE_CACHE) $(BUILD)
+ @rm -rf $(WORK_PATH) $(BASE_CACHE) $(BUILD) *.log
install: check-packages $(host_prefix)/share/config.site
diff --git a/depends/README.md b/depends/README.md
index f7647198c6..da2a74e0e7 100644
--- a/depends/README.md
+++ b/depends/README.md
@@ -113,7 +113,10 @@ The following can be set when running make: `make FOO=bar`
- `BUILD_ID_SALT`: Optional salt to use when generating build package ids
- `FORCE_USE_SYSTEM_CLANG`: (EXPERTS ONLY) When cross-compiling for macOS, use Clang found in the
system's `$PATH` rather than the default prebuilt release of Clang
- from llvm.org. Clang 8 or later is required.
+ from llvm.org. Clang 8 or later is required
+- `LOG`: Use file-based logging for individual packages. During a package build its log file
+ resides in the `depends` directory, and the log file is printed out automatically in case
+ of build error. After successful build log files are moved along with package archives
If some packages are not built, for example `make NO_WALLET=1`, the appropriate
options will be passed to bitcoin's configure. In this case, `--disable-wallet`.
diff --git a/depends/funcs.mk b/depends/funcs.mk
index c4ad109c69..75fa1ed43f 100644
--- a/depends/funcs.mk
+++ b/depends/funcs.mk
@@ -67,6 +67,7 @@ $(1)_cached_checksum:=$(BASE_CACHE)/$(host)/$(1)/$(1)-$($(1)_version)-$($(1)_bui
$(1)_patch_dir:=$(base_build_dir)/$(host)/$(1)/$($(1)_version)-$($(1)_build_id)/.patches-$($(1)_build_id)
$(1)_prefixbin:=$($($(1)_type)_prefix)/bin/
$(1)_cached:=$(BASE_CACHE)/$(host)/$(1)/$(1)-$($(1)_version)-$($(1)_build_id).tar.gz
+$(1)_build_log:=$(BASEDIR)/$(1)-$($(1)_version)-$($(1)_build_id).log
$(1)_all_sources=$($(1)_file_name) $($(1)_extra_sources)
#stamps
@@ -85,7 +86,7 @@ $(1)_download_path_fixed=$(subst :,\:,$$($(1)_download_path))
# The default behavior for tar will try to set ownership when running as uid 0 and may not succeed, --no-same-owner disables this behavior
$(1)_fetch_cmds ?= $(call fetch_file,$(1),$(subst \:,:,$$($(1)_download_path_fixed)),$$($(1)_download_file),$($(1)_file_name),$($(1)_sha256_hash))
$(1)_extract_cmds ?= mkdir -p $$($(1)_extract_dir) && echo "$$($(1)_sha256_hash) $$($(1)_source)" > $$($(1)_extract_dir)/.$$($(1)_file_name).hash && $(build_SHA256SUM) -c $$($(1)_extract_dir)/.$$($(1)_file_name).hash && $(build_TAR) --no-same-owner --strip-components=1 -xf $$($(1)_source)
-$(1)_preprocess_cmds ?=
+$(1)_preprocess_cmds ?= true
$(1)_build_cmds ?=
$(1)_config_cmds ?=
$(1)_stage_cmds ?=
@@ -187,44 +188,48 @@ endif
endef
define int_add_cmds
+ifneq ($(LOG),)
+$(1)_logging = >>$$($(1)_build_log) 2>&1 || { if test -f $$($(1)_build_log); then cat $$($(1)_build_log); fi; exit 1; }
+endif
+
$($(1)_fetched):
mkdir -p $$(@D) $(SOURCES_PATH)
rm -f $$@
touch $$@
- cd $$(@D); $(call $(1)_fetch_cmds,$(1))
+ cd $$(@D); $($(1)_fetch_cmds)
cd $($(1)_source_dir); $(foreach source,$($(1)_all_sources),$(build_SHA256SUM) $(source) >> $$(@);)
touch $$@
$($(1)_extracted): | $($(1)_fetched)
echo Extracting $(1)...
mkdir -p $$(@D)
- cd $$(@D); $(call $(1)_extract_cmds,$(1))
+ cd $$(@D); $($(1)_extract_cmds)
touch $$@
$($(1)_preprocessed): | $($(1)_extracted)
echo Preprocessing $(1)...
mkdir -p $$(@D) $($(1)_patch_dir)
$(foreach patch,$($(1)_patches),cd $(PATCHES_PATH)/$(1); cp $(patch) $($(1)_patch_dir) ;)
- cd $$(@D); $(call $(1)_preprocess_cmds, $(1))
+ { cd $$(@D); $($(1)_preprocess_cmds); } $$($(1)_logging)
touch $$@
$($(1)_configured): | $($(1)_dependencies) $($(1)_preprocessed)
echo Configuring $(1)...
rm -rf $(host_prefix); mkdir -p $(host_prefix)/lib; cd $(host_prefix); $(foreach package,$($(1)_all_dependencies), $(build_TAR) --no-same-owner -xf $($(package)_cached); )
mkdir -p $$(@D)
- +cd $$(@D); $($(1)_config_env) $(call $(1)_config_cmds, $(1))
+ +{ cd $$(@D); $($(1)_config_env) $($(1)_config_cmds); } $$($(1)_logging)
touch $$@
$($(1)_built): | $($(1)_configured)
echo Building $(1)...
mkdir -p $$(@D)
- +cd $$(@D); $($(1)_build_env) $(call $(1)_build_cmds, $(1))
+ +{ cd $$(@D); $($(1)_build_env) $($(1)_build_cmds); } $$($(1)_logging)
touch $$@
$($(1)_staged): | $($(1)_built)
echo Staging $(1)...
mkdir -p $($(1)_staging_dir)/$(host_prefix)
- cd $($(1)_build_dir); $($(1)_stage_env) $(call $(1)_stage_cmds, $(1))
+ +{ cd $($(1)_build_dir); $($(1)_stage_env) $($(1)_stage_cmds); } $$($(1)_logging)
rm -rf $($(1)_extract_dir)
touch $$@
$($(1)_postprocessed): | $($(1)_staged)
echo Postprocessing $(1)...
- cd $($(1)_staging_prefix_dir); $(call $(1)_postprocess_cmds)
+ cd $($(1)_staging_prefix_dir); $($(1)_postprocess_cmds)
touch $$@
$($(1)_cached): | $($(1)_dependencies) $($(1)_postprocessed)
echo Caching $(1)...
@@ -233,6 +238,7 @@ $($(1)_cached): | $($(1)_dependencies) $($(1)_postprocessed)
rm -rf $$(@D) && mkdir -p $$(@D)
mv $$($(1)_staging_dir)/$$(@F) $$(@)
rm -rf $($(1)_staging_dir)
+ if test -f $($(1)_build_log); then mv $($(1)_build_log) $$(@D); fi
$($(1)_cached_checksum): $($(1)_cached)
cd $$(@D); $(build_SHA256SUM) $$(<F) > $$(@)
diff --git a/doc/REST-interface.md b/doc/REST-interface.md
index c359725faf..f11624fd28 100644
--- a/doc/REST-interface.md
+++ b/doc/REST-interface.md
@@ -82,17 +82,7 @@ Given a height: returns hash of block in best-block-chain at height provided.
Returns various state info regarding block chain processing.
Only supports JSON as output format.
-* chain : (string) current network name (main, test, signet, regtest)
-* blocks : (numeric) the current number of blocks processed in the server
-* headers : (numeric) the current number of headers we have validated
-* bestblockhash : (string) the hash of the currently best block
-* difficulty : (numeric) the current difficulty
-* mediantime : (numeric) the median time of the 11 blocks before the most recent block on the blockchain
-* verificationprogress : (numeric) estimate of verification progress [0..1]
-* chainwork : (string) total amount of work in active chain, in hexadecimal
-* pruned : (boolean) if the blocks are subject to pruning
-* pruneheight : (numeric) highest block available
-* softforks : (array) status of softforks in progress
+Refer to the `getblockchaininfo` RPC help for details.
#### Query UTXO set
`GET /rest/getutxos/<checkmempool>/<txid>-<n>/<txid>-<n>/.../<txid>-<n>.<bin|hex|json>`
@@ -127,13 +117,13 @@ $ curl localhost:18332/rest/getutxos/checkmempool/b2cdfd7b89def827ff8af7cd9bff76
#### Memory pool
`GET /rest/mempool/info.json`
-Returns various information about the TX mempool.
+Returns various information about the transaction mempool.
Only supports JSON as output format.
-Refer to the `getmempoolinfo` RPC for documentation of the fields.
+Refer to the `getmempoolinfo` RPC help for details.
`GET /rest/mempool/contents.json`
-Returns transactions in the TX mempool.
+Returns the transactions in the mempool.
Only supports JSON as output format.
Risks
diff --git a/doc/release-process.md b/doc/release-process.md
index bc80e3d072..2f3a163a8e 100644
--- a/doc/release-process.md
+++ b/doc/release-process.md
@@ -37,7 +37,8 @@ Release Process
- This update should be reviewed with a reindex-chainstate with assumevalid=0 to catch any defect
that causes rejection of blocks in the past history.
- Clear the release notes and move them to the wiki (see "Write the release notes" below).
-- Translations on Transifex
+- Translations on Transifex:
+ - Pull translations from Transifex into the master branch.
- Create [a new resource](https://www.transifex.com/bitcoin/bitcoin/content/) named after the major version with the slug `[bitcoin.qt-translation-<RRR>x]`, where `RRR` is the major branch number padded with zeros. Use `src/qt/locale/bitcoin_en.xlf` to create it.
- In the project workflow settings, ensure that [Translation Memory Fill-up](https://docs.transifex.com/translation-memory/enabling-autofill) is enabled and that [Translation Memory Context Matching](https://docs.transifex.com/translation-memory/translation-memory-with-context) is disabled.
- Update the Transifex slug in [`.tx/config`](/.tx/config) to the slug of the resource created in the first step. This identifies which resource the translations will be synchronized from.
diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include
index 5dae4374e3..58a09cd4a4 100644
--- a/src/Makefile.bench.include
+++ b/src/Makefile.bench.include
@@ -74,6 +74,7 @@ endif
if ENABLE_WALLET
bench_bench_bitcoin_SOURCES += bench/coin_selection.cpp
bench_bench_bitcoin_SOURCES += bench/wallet_balance.cpp
+bench_bench_bitcoin_SOURCES += bench/wallet_loading.cpp
endif
bench_bench_bitcoin_LDADD += $(BDB_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(MINIUPNPC_LIBS) $(NATPMP_LIBS) $(SQLITE_LIBS)
diff --git a/src/arith_uint256.cpp b/src/arith_uint256.cpp
index f7f62dfc68..e614102de3 100644
--- a/src/arith_uint256.cpp
+++ b/src/arith_uint256.cpp
@@ -146,13 +146,21 @@ double base_uint<BITS>::getdouble() const
template <unsigned int BITS>
std::string base_uint<BITS>::GetHex() const
{
- return ArithToUint256(*this).GetHex();
+ base_blob<BITS> b;
+ for (int x = 0; x < this->WIDTH; ++x) {
+ WriteLE32(b.begin() + x*4, this->pn[x]);
+ }
+ return b.GetHex();
}
template <unsigned int BITS>
void base_uint<BITS>::SetHex(const char* psz)
{
- *this = UintToArith256(uint256S(psz));
+ base_blob<BITS> b;
+ b.SetHex(psz);
+ for (int x = 0; x < this->WIDTH; ++x) {
+ this->pn[x] = ReadLE32(b.begin() + x*4);
+ }
}
template <unsigned int BITS>
@@ -164,7 +172,7 @@ void base_uint<BITS>::SetHex(const std::string& str)
template <unsigned int BITS>
std::string base_uint<BITS>::ToString() const
{
- return (GetHex());
+ return GetHex();
}
template <unsigned int BITS>
@@ -183,20 +191,7 @@ unsigned int base_uint<BITS>::bits() const
}
// Explicit instantiations for base_uint<256>
-template base_uint<256>::base_uint(const std::string&);
-template base_uint<256>& base_uint<256>::operator<<=(unsigned int);
-template base_uint<256>& base_uint<256>::operator>>=(unsigned int);
-template base_uint<256>& base_uint<256>::operator*=(uint32_t b32);
-template base_uint<256>& base_uint<256>::operator*=(const base_uint<256>& b);
-template base_uint<256>& base_uint<256>::operator/=(const base_uint<256>& b);
-template int base_uint<256>::CompareTo(const base_uint<256>&) const;
-template bool base_uint<256>::EqualTo(uint64_t) const;
-template double base_uint<256>::getdouble() const;
-template std::string base_uint<256>::GetHex() const;
-template std::string base_uint<256>::ToString() const;
-template void base_uint<256>::SetHex(const char*);
-template void base_uint<256>::SetHex(const std::string&);
-template unsigned int base_uint<256>::bits() const;
+template class base_uint<256>;
// This implementation directly uses shifts instead of going
// through an intermediate MPI representation.
diff --git a/src/arith_uint256.h b/src/arith_uint256.h
index a0a0429c2a..19193972a4 100644
--- a/src/arith_uint256.h
+++ b/src/arith_uint256.h
@@ -284,4 +284,6 @@ public:
uint256 ArithToUint256(const arith_uint256 &);
arith_uint256 UintToArith256(const uint256 &);
+extern template class base_uint<256>;
+
#endif // BITCOIN_ARITH_UINT256_H
diff --git a/src/bench/wallet_loading.cpp b/src/bench/wallet_loading.cpp
new file mode 100644
index 0000000000..38d3460001
--- /dev/null
+++ b/src/bench/wallet_loading.cpp
@@ -0,0 +1,83 @@
+// Copyright (c) 2022 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 <bench/bench.h>
+#include <interfaces/chain.h>
+#include <node/context.h>
+#include <test/util/mining.h>
+#include <test/util/setup_common.h>
+#include <test/util/wallet.h>
+#include <util/translation.h>
+#include <validationinterface.h>
+#include <wallet/context.h>
+#include <wallet/receive.h>
+#include <wallet/wallet.h>
+
+#include <optional>
+
+using wallet::CWallet;
+using wallet::DatabaseOptions;
+using wallet::DatabaseStatus;
+using wallet::ISMINE_SPENDABLE;
+using wallet::MakeWalletDatabase;
+using wallet::WALLET_FLAG_DESCRIPTORS;
+using wallet::WalletContext;
+
+static const std::shared_ptr<CWallet> BenchLoadWallet(WalletContext& context, DatabaseOptions& options)
+{
+ DatabaseStatus status;
+ bilingual_str error;
+ std::vector<bilingual_str> warnings;
+ auto database = MakeWalletDatabase("", options, status, error);
+ assert(database);
+ auto wallet = CWallet::Create(context, "", std::move(database), options.create_flags, error, warnings);
+ NotifyWalletLoaded(context, wallet);
+ if (context.chain) {
+ wallet->postInitProcess();
+ }
+ return wallet;
+}
+
+static void BenchUnloadWallet(std::shared_ptr<CWallet>&& wallet)
+{
+ SyncWithValidationInterfaceQueue();
+ wallet->m_chain_notifications_handler.reset();
+ UnloadWallet(std::move(wallet));
+}
+
+static void WalletLoading(benchmark::Bench& bench, bool legacy_wallet)
+{
+ const auto test_setup = MakeNoLogFileContext<TestingSetup>();
+
+ WalletContext context;
+ context.args = &test_setup->m_args;
+ context.chain = test_setup->m_node.chain.get();
+
+ // Setup the wallet
+ // Loading the wallet will also create it
+ DatabaseOptions options;
+ if (!legacy_wallet) options.create_flags = WALLET_FLAG_DESCRIPTORS;
+ auto wallet = BenchLoadWallet(context, options);
+
+ // Generate a bunch of transactions and addresses to put into the wallet
+ for (int i = 0; i < 5000; ++i) {
+ generatetoaddress(test_setup->m_node, getnewaddress(*wallet));
+ }
+
+ // reload the wallet for the actual benchmark
+ BenchUnloadWallet(std::move(wallet));
+
+ bench.minEpochIterations(10).run([&] {
+ wallet = BenchLoadWallet(context, options);
+
+ // Cleanup
+ BenchUnloadWallet(std::move(wallet));
+ });
+}
+
+static void WalletLoadingLegacy(benchmark::Bench& bench) { WalletLoading(bench, /*legacy_wallet=*/true); }
+static void WalletLoadingDescriptors(benchmark::Bench& bench) { WalletLoading(bench, /*legacy_wallet=*/false); }
+
+BENCHMARK(WalletLoadingLegacy);
+BENCHMARK(WalletLoadingDescriptors);
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index 6925a4c8c6..dea46693bc 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -1055,7 +1055,9 @@ static void ParseGetInfoResult(UniValue& result)
result_string += "\n";
}
- result_string += strprintf("%sWarnings:%s %s", YELLOW, RESET, result["warnings"].getValStr());
+ const std::string warnings{result["warnings"].getValStr()};
+ result_string += strprintf("%sWarnings:%s %s", YELLOW, RESET, warnings.empty() ? "(none)" : warnings);
+
result.setStr(result_string);
}
diff --git a/src/init.cpp b/src/init.cpp
index 86e6ec4451..fdab296593 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -660,7 +660,8 @@ void InitParameterInteraction(ArgsManager& args)
LogPrintf("%s: parameter interaction: -connect set -> setting -listen=0\n", __func__);
}
- if (args.IsArgSet("-proxy")) {
+ std::string proxy_arg = args.GetArg("-proxy", "");
+ if (proxy_arg != "" && proxy_arg != "0") {
// to protect privacy, do not listen by default if a default proxy server is specified
if (args.SoftSetBoolArg("-listen", false))
LogPrintf("%s: parameter interaction: -proxy set -> setting -listen=0\n", __func__);
diff --git a/src/logging/timer.h b/src/logging/timer.h
index fc5307bc62..d954e46301 100644
--- a/src/logging/timer.h
+++ b/src/logging/timer.h
@@ -97,13 +97,13 @@ private:
#define LOG_TIME_MICROS_WITH_CATEGORY(end_msg, log_category) \
- BCLog::Timer<std::chrono::microseconds> PASTE2(logging_timer, __COUNTER__)(__func__, end_msg, log_category)
+ BCLog::Timer<std::chrono::microseconds> UNIQUE_NAME(logging_timer)(__func__, end_msg, log_category)
#define LOG_TIME_MILLIS_WITH_CATEGORY(end_msg, log_category) \
- BCLog::Timer<std::chrono::milliseconds> PASTE2(logging_timer, __COUNTER__)(__func__, end_msg, log_category)
+ BCLog::Timer<std::chrono::milliseconds> UNIQUE_NAME(logging_timer)(__func__, end_msg, log_category)
#define LOG_TIME_MILLIS_WITH_CATEGORY_MSG_ONCE(end_msg, log_category) \
- BCLog::Timer<std::chrono::milliseconds> PASTE2(logging_timer, __COUNTER__)(__func__, end_msg, log_category, /* msg_on_completion=*/false)
+ BCLog::Timer<std::chrono::milliseconds> UNIQUE_NAME(logging_timer)(__func__, end_msg, log_category, /* msg_on_completion=*/false)
#define LOG_TIME_SECONDS(end_msg) \
- BCLog::Timer<std::chrono::seconds> PASTE2(logging_timer, __COUNTER__)(__func__, end_msg)
+ BCLog::Timer<std::chrono::seconds> UNIQUE_NAME(logging_timer)(__func__, end_msg)
#endif // BITCOIN_LOGGING_TIMER_H
diff --git a/src/netbase.cpp b/src/netbase.cpp
index 9a0b800565..e6d4f16ba0 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -305,7 +305,7 @@ enum class IntrRecvError {
*
* @see This function can be interrupted by calling InterruptSocks5(bool).
* Sockets can be made non-blocking with SetSocketNonBlocking(const
- * SOCKET&, bool).
+ * SOCKET&).
*/
static IntrRecvError InterruptibleRecv(uint8_t* data, size_t len, int timeout, const Sock& sock)
{
@@ -518,7 +518,7 @@ std::unique_ptr<Sock> CreateSockTCP(const CService& address_family)
SetSocketNoDelay(hSocket);
// Set the non-blocking option on the socket.
- if (!SetSocketNonBlocking(hSocket, true)) {
+ if (!SetSocketNonBlocking(hSocket)) {
CloseSocket(hSocket);
LogPrintf("Error setting socket to non-blocking: %s\n", NetworkErrorString(WSAGetLastError()));
return nullptr;
@@ -711,28 +711,16 @@ bool LookupSubNet(const std::string& subnet_str, CSubNet& subnet_out)
return false;
}
-bool SetSocketNonBlocking(const SOCKET& hSocket, bool fNonBlocking)
+bool SetSocketNonBlocking(const SOCKET& hSocket)
{
- if (fNonBlocking) {
#ifdef WIN32
- u_long nOne = 1;
- if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR) {
+ u_long nOne = 1;
+ if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR) {
#else
- int fFlags = fcntl(hSocket, F_GETFL, 0);
- if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == SOCKET_ERROR) {
+ int fFlags = fcntl(hSocket, F_GETFL, 0);
+ if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == SOCKET_ERROR) {
#endif
- return false;
- }
- } else {
-#ifdef WIN32
- u_long nZero = 0;
- if (ioctlsocket(hSocket, FIONBIO, &nZero) == SOCKET_ERROR) {
-#else
- int fFlags = fcntl(hSocket, F_GETFL, 0);
- if (fcntl(hSocket, F_SETFL, fFlags & ~O_NONBLOCK) == SOCKET_ERROR) {
-#endif
- return false;
- }
+ return false;
}
return true;
diff --git a/src/netbase.h b/src/netbase.h
index f9e3872c16..c226e6b73d 100644
--- a/src/netbase.h
+++ b/src/netbase.h
@@ -221,8 +221,8 @@ bool ConnectSocketDirectly(const CService &addrConnect, const Sock& sock, int nT
*/
bool ConnectThroughProxy(const Proxy& proxy, const std::string& strDest, uint16_t port, const Sock& sock, int nTimeout, bool& outProxyConnectionFailed);
-/** Disable or enable blocking-mode for a socket */
-bool SetSocketNonBlocking(const SOCKET& hSocket, bool fNonBlocking);
+/** Enable non-blocking mode for a socket */
+bool SetSocketNonBlocking(const SOCKET& hSocket);
/** Set the TCP_NODELAY flag on a socket */
bool SetSocketNoDelay(const SOCKET& hSocket);
void InterruptSocks5(bool interrupt);
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index c6b884e40a..8cac28400f 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -95,6 +95,8 @@ static void RegisterMetaTypes()
qRegisterMetaType<std::function<void()>>("std::function<void()>");
qRegisterMetaType<QMessageBox::Icon>("QMessageBox::Icon");
qRegisterMetaType<interfaces::BlockAndHeaderTipInfo>("interfaces::BlockAndHeaderTipInfo");
+
+ qRegisterMetaTypeStreamOperators<BitcoinUnit>("BitcoinUnit");
}
static QString GetLangTerritory()
diff --git a/src/qt/bitcoinamountfield.cpp b/src/qt/bitcoinamountfield.cpp
index a257e250e0..c92aecd095 100644
--- a/src/qt/bitcoinamountfield.cpp
+++ b/src/qt/bitcoinamountfield.cpp
@@ -14,6 +14,9 @@
#include <QHBoxLayout>
#include <QKeyEvent>
#include <QLineEdit>
+#include <QVariant>
+
+#include <cassert>
/** QSpinBox that uses fixed-point numbers internally and uses our own
* formatting/parsing functions.
@@ -96,7 +99,7 @@ public:
setValue(val);
}
- void setDisplayUnit(int unit)
+ void setDisplayUnit(BitcoinUnit unit)
{
bool valid = false;
CAmount val = value(&valid);
@@ -122,7 +125,7 @@ public:
const QFontMetrics fm(fontMetrics());
int h = lineEdit()->minimumSizeHint().height();
- int w = GUIUtil::TextWidth(fm, BitcoinUnits::format(BitcoinUnits::BTC, BitcoinUnits::maxMoney(), false, BitcoinUnits::SeparatorStyle::ALWAYS));
+ int w = GUIUtil::TextWidth(fm, BitcoinUnits::format(BitcoinUnit::BTC, BitcoinUnits::maxMoney(), false, BitcoinUnits::SeparatorStyle::ALWAYS));
w += 2; // cursor blinking space
QStyleOptionSpinBox opt;
@@ -141,14 +144,13 @@ public:
opt.rect = rect();
- cachedMinimumSizeHint = style()->sizeFromContents(QStyle::CT_SpinBox, &opt, hint, this)
- .expandedTo(QApplication::globalStrut());
+ cachedMinimumSizeHint = style()->sizeFromContents(QStyle::CT_SpinBox, &opt, hint, this);
}
return cachedMinimumSizeHint;
}
private:
- int currentUnit{BitcoinUnits::BTC};
+ BitcoinUnit currentUnit{BitcoinUnit::BTC};
CAmount singleStep{CAmount(100000)}; // satoshis
mutable QSize cachedMinimumSizeHint;
bool m_allow_empty{true};
@@ -326,14 +328,14 @@ void BitcoinAmountField::unitChanged(int idx)
unit->setToolTip(unit->itemData(idx, Qt::ToolTipRole).toString());
// Determine new unit ID
- int newUnit = unit->itemData(idx, BitcoinUnits::UnitRole).toInt();
-
- amount->setDisplayUnit(newUnit);
+ QVariant new_unit = unit->currentData(BitcoinUnits::UnitRole);
+ assert(new_unit.isValid());
+ amount->setDisplayUnit(new_unit.value<BitcoinUnit>());
}
-void BitcoinAmountField::setDisplayUnit(int newUnit)
+void BitcoinAmountField::setDisplayUnit(BitcoinUnit new_unit)
{
- unit->setValue(newUnit);
+ unit->setValue(QVariant::fromValue(new_unit));
}
void BitcoinAmountField::setSingleStep(const CAmount& step)
diff --git a/src/qt/bitcoinamountfield.h b/src/qt/bitcoinamountfield.h
index 366a6fc4b5..a40cd38332 100644
--- a/src/qt/bitcoinamountfield.h
+++ b/src/qt/bitcoinamountfield.h
@@ -6,6 +6,7 @@
#define BITCOIN_QT_BITCOINAMOUNTFIELD_H
#include <consensus/amount.h>
+#include <qt/bitcoinunits.h>
#include <QWidget>
@@ -52,7 +53,7 @@ public:
bool validate();
/** Change unit used to display amount. */
- void setDisplayUnit(int unit);
+ void setDisplayUnit(BitcoinUnit new_unit);
/** Make field empty and ready for new input. */
void clear();
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index be0d33d667..81b0e711b2 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -1245,7 +1245,7 @@ void BitcoinGUI::showEvent(QShowEvent *event)
}
#ifdef ENABLE_WALLET
-void BitcoinGUI::incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label, const QString& walletName)
+void BitcoinGUI::incomingTransaction(const QString& date, BitcoinUnit unit, const CAmount& amount, const QString& type, const QString& address, const QString& label, const QString& walletName)
{
// On new transaction, make an info balloon
QString msg = tr("Date: %1\n").arg(date) +
@@ -1496,11 +1496,10 @@ UnitDisplayStatusBarControl::UnitDisplayStatusBarControl(const PlatformStyle *pl
{
createContextMenu();
setToolTip(tr("Unit to show amounts in. Click to select another unit."));
- QList<BitcoinUnits::Unit> units = BitcoinUnits::availableUnits();
+ QList<BitcoinUnit> units = BitcoinUnits::availableUnits();
int max_width = 0;
const QFontMetrics fm(font());
- for (const BitcoinUnits::Unit unit : units)
- {
+ for (const BitcoinUnit unit : units) {
max_width = qMax(max_width, GUIUtil::TextWidth(fm, BitcoinUnits::longName(unit)));
}
setMinimumSize(max_width, 0);
@@ -1530,8 +1529,8 @@ void UnitDisplayStatusBarControl::changeEvent(QEvent* e)
void UnitDisplayStatusBarControl::createContextMenu()
{
menu = new QMenu(this);
- for (const BitcoinUnits::Unit u : BitcoinUnits::availableUnits()) {
- menu->addAction(BitcoinUnits::longName(u))->setData(QVariant(u));
+ for (const BitcoinUnit u : BitcoinUnits::availableUnits()) {
+ menu->addAction(BitcoinUnits::longName(u))->setData(QVariant::fromValue(u));
}
connect(menu, &QMenu::triggered, this, &UnitDisplayStatusBarControl::onMenuSelection);
}
@@ -1552,7 +1551,7 @@ void UnitDisplayStatusBarControl::setOptionsModel(OptionsModel *_optionsModel)
}
/** When Display Units are changed on OptionsModel it will refresh the display text of the control on the status bar */
-void UnitDisplayStatusBarControl::updateDisplayUnit(int newUnits)
+void UnitDisplayStatusBarControl::updateDisplayUnit(BitcoinUnit newUnits)
{
setText(BitcoinUnits::longName(newUnits));
}
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index d2b29ba27b..5d9a978695 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -9,6 +9,7 @@
#include <config/bitcoin-config.h>
#endif
+#include <qt/bitcoinunits.h>
#include <qt/guiutil.h>
#include <qt/optionsdialog.h>
@@ -260,7 +261,7 @@ public Q_SLOTS:
bool handlePaymentRequest(const SendCoinsRecipient& recipient);
/** Show incoming transaction notification for new transactions. */
- void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label, const QString& walletName);
+ void incomingTransaction(const QString& date, BitcoinUnit unit, const CAmount& amount, const QString& type, const QString& address, const QString& label, const QString& walletName);
#endif // ENABLE_WALLET
private:
@@ -341,7 +342,7 @@ private:
private Q_SLOTS:
/** When Display Units are changed on OptionsModel it will refresh the display text of the control on the status bar */
- void updateDisplayUnit(int newUnits);
+ void updateDisplayUnit(BitcoinUnit newUnits);
/** Tells underlying optionsModel to update its current display unit. */
void onMenuSelection(QAction* action);
};
diff --git a/src/qt/bitcoinunits.cpp b/src/qt/bitcoinunits.cpp
index 69caf64d5c..fe3eb3240b 100644
--- a/src/qt/bitcoinunits.cpp
+++ b/src/qt/bitcoinunits.cpp
@@ -18,94 +18,75 @@ BitcoinUnits::BitcoinUnits(QObject *parent):
{
}
-QList<BitcoinUnits::Unit> BitcoinUnits::availableUnits()
+QList<BitcoinUnit> BitcoinUnits::availableUnits()
{
- QList<BitcoinUnits::Unit> unitlist;
- unitlist.append(BTC);
- unitlist.append(mBTC);
- unitlist.append(uBTC);
- unitlist.append(SAT);
+ QList<BitcoinUnit> unitlist;
+ unitlist.append(Unit::BTC);
+ unitlist.append(Unit::mBTC);
+ unitlist.append(Unit::uBTC);
+ unitlist.append(Unit::SAT);
return unitlist;
}
-bool BitcoinUnits::valid(int unit)
+QString BitcoinUnits::longName(Unit unit)
{
- switch(unit)
- {
- case BTC:
- case mBTC:
- case uBTC:
- case SAT:
- return true;
- default:
- return false;
- }
-}
-
-QString BitcoinUnits::longName(int unit)
-{
- switch(unit)
- {
- case BTC: return QString("BTC");
- case mBTC: return QString("mBTC");
- case uBTC: return QString::fromUtf8("µBTC (bits)");
- case SAT: return QString("Satoshi (sat)");
- default: return QString("???");
- }
+ switch (unit) {
+ case Unit::BTC: return QString("BTC");
+ case Unit::mBTC: return QString("mBTC");
+ case Unit::uBTC: return QString::fromUtf8("µBTC (bits)");
+ case Unit::SAT: return QString("Satoshi (sat)");
+ } // no default case, so the compiler can warn about missing cases
+ assert(false);
}
-QString BitcoinUnits::shortName(int unit)
+QString BitcoinUnits::shortName(Unit unit)
{
- switch(unit)
- {
- case uBTC: return QString::fromUtf8("bits");
- case SAT: return QString("sat");
- default: return longName(unit);
- }
+ switch (unit) {
+ case Unit::BTC: return longName(unit);
+ case Unit::mBTC: return longName(unit);
+ case Unit::uBTC: return QString("bits");
+ case Unit::SAT: return QString("sat");
+ } // no default case, so the compiler can warn about missing cases
+ assert(false);
}
-QString BitcoinUnits::description(int unit)
+QString BitcoinUnits::description(Unit unit)
{
- switch(unit)
- {
- case BTC: return QString("Bitcoins");
- case mBTC: return QString("Milli-Bitcoins (1 / 1" THIN_SP_UTF8 "000)");
- case uBTC: return QString("Micro-Bitcoins (bits) (1 / 1" THIN_SP_UTF8 "000" THIN_SP_UTF8 "000)");
- case SAT: return QString("Satoshi (sat) (1 / 100" THIN_SP_UTF8 "000" THIN_SP_UTF8 "000)");
- default: return QString("???");
- }
+ switch (unit) {
+ case Unit::BTC: return QString("Bitcoins");
+ case Unit::mBTC: return QString("Milli-Bitcoins (1 / 1" THIN_SP_UTF8 "000)");
+ case Unit::uBTC: return QString("Micro-Bitcoins (bits) (1 / 1" THIN_SP_UTF8 "000" THIN_SP_UTF8 "000)");
+ case Unit::SAT: return QString("Satoshi (sat) (1 / 100" THIN_SP_UTF8 "000" THIN_SP_UTF8 "000)");
+ } // no default case, so the compiler can warn about missing cases
+ assert(false);
}
-qint64 BitcoinUnits::factor(int unit)
+qint64 BitcoinUnits::factor(Unit unit)
{
- switch(unit)
- {
- case BTC: return 100000000;
- case mBTC: return 100000;
- case uBTC: return 100;
- case SAT: return 1;
- default: return 100000000;
- }
+ switch (unit) {
+ case Unit::BTC: return 100'000'000;
+ case Unit::mBTC: return 100'000;
+ case Unit::uBTC: return 100;
+ case Unit::SAT: return 1;
+ } // no default case, so the compiler can warn about missing cases
+ assert(false);
}
-int BitcoinUnits::decimals(int unit)
+int BitcoinUnits::decimals(Unit unit)
{
- switch(unit)
- {
- case BTC: return 8;
- case mBTC: return 5;
- case uBTC: return 2;
- case SAT: return 0;
- default: return 0;
- }
+ switch (unit) {
+ case Unit::BTC: return 8;
+ case Unit::mBTC: return 5;
+ case Unit::uBTC: return 2;
+ case Unit::SAT: return 0;
+ } // no default case, so the compiler can warn about missing cases
+ assert(false);
}
-QString BitcoinUnits::format(int unit, const CAmount& nIn, bool fPlus, SeparatorStyle separators, bool justify)
+QString BitcoinUnits::format(Unit unit, const CAmount& nIn, bool fPlus, SeparatorStyle separators, bool justify)
{
// Note: not using straight sprintf here because we do NOT want
// localized number formatting.
- if(!valid(unit))
- return QString(); // Refuse to format invalid unit
qint64 n = (qint64)nIn;
qint64 coin = factor(unit);
int num_decimals = decimals(unit);
@@ -147,19 +128,19 @@ QString BitcoinUnits::format(int unit, const CAmount& nIn, bool fPlus, Separator
// Please take care to use formatHtmlWithUnit instead, when
// appropriate.
-QString BitcoinUnits::formatWithUnit(int unit, const CAmount& amount, bool plussign, SeparatorStyle separators)
+QString BitcoinUnits::formatWithUnit(Unit unit, const CAmount& amount, bool plussign, SeparatorStyle separators)
{
return format(unit, amount, plussign, separators) + QString(" ") + shortName(unit);
}
-QString BitcoinUnits::formatHtmlWithUnit(int unit, const CAmount& amount, bool plussign, SeparatorStyle separators)
+QString BitcoinUnits::formatHtmlWithUnit(Unit unit, const CAmount& amount, bool plussign, SeparatorStyle separators)
{
QString str(formatWithUnit(unit, amount, plussign, separators));
str.replace(QChar(THIN_SP_CP), QString(THIN_SP_HTML));
return QString("<span style='white-space: nowrap;'>%1</span>").arg(str);
}
-QString BitcoinUnits::formatWithPrivacy(int unit, const CAmount& amount, SeparatorStyle separators, bool privacy)
+QString BitcoinUnits::formatWithPrivacy(Unit unit, const CAmount& amount, SeparatorStyle separators, bool privacy)
{
assert(amount >= 0);
QString value;
@@ -171,10 +152,11 @@ QString BitcoinUnits::formatWithPrivacy(int unit, const CAmount& amount, Separat
return value + QString(" ") + shortName(unit);
}
-bool BitcoinUnits::parse(int unit, const QString &value, CAmount *val_out)
+bool BitcoinUnits::parse(Unit unit, const QString& value, CAmount* val_out)
{
- if(!valid(unit) || value.isEmpty())
+ if (value.isEmpty()) {
return false; // Refuse to parse invalid unit or empty string
+ }
int num_decimals = decimals(unit);
// Ignore spaces and thin spaces when parsing
@@ -210,14 +192,9 @@ bool BitcoinUnits::parse(int unit, const QString &value, CAmount *val_out)
return ok;
}
-QString BitcoinUnits::getAmountColumnTitle(int unit)
+QString BitcoinUnits::getAmountColumnTitle(Unit unit)
{
- QString amountTitle = QObject::tr("Amount");
- if (BitcoinUnits::valid(unit))
- {
- amountTitle += " ("+BitcoinUnits::shortName(unit) + ")";
- }
- return amountTitle;
+ return QObject::tr("Amount") + " (" + shortName(unit) + ")";
}
int BitcoinUnits::rowCount(const QModelIndex &parent) const
@@ -240,7 +217,7 @@ QVariant BitcoinUnits::data(const QModelIndex &index, int role) const
case Qt::ToolTipRole:
return QVariant(description(unit));
case UnitRole:
- return QVariant(static_cast<int>(unit));
+ return QVariant::fromValue(unit);
}
}
return QVariant();
@@ -250,3 +227,40 @@ CAmount BitcoinUnits::maxMoney()
{
return MAX_MONEY;
}
+
+namespace {
+qint8 ToQint8(BitcoinUnit unit)
+{
+ switch (unit) {
+ case BitcoinUnit::BTC: return 0;
+ case BitcoinUnit::mBTC: return 1;
+ case BitcoinUnit::uBTC: return 2;
+ case BitcoinUnit::SAT: return 3;
+ } // no default case, so the compiler can warn about missing cases
+ assert(false);
+}
+
+BitcoinUnit FromQint8(qint8 num)
+{
+ switch (num) {
+ case 0: return BitcoinUnit::BTC;
+ case 1: return BitcoinUnit::mBTC;
+ case 2: return BitcoinUnit::uBTC;
+ case 3: return BitcoinUnit::SAT;
+ }
+ assert(false);
+}
+} // namespace
+
+QDataStream& operator<<(QDataStream& out, const BitcoinUnit& unit)
+{
+ return out << ToQint8(unit);
+}
+
+QDataStream& operator>>(QDataStream& in, BitcoinUnit& unit)
+{
+ qint8 input;
+ in >> input;
+ unit = FromQint8(input);
+ return in;
+}
diff --git a/src/qt/bitcoinunits.h b/src/qt/bitcoinunits.h
index 9fedec0d4f..b3b5a8fc18 100644
--- a/src/qt/bitcoinunits.h
+++ b/src/qt/bitcoinunits.h
@@ -8,6 +8,7 @@
#include <consensus/amount.h>
#include <QAbstractListModel>
+#include <QDataStream>
#include <QString>
// U+2009 THIN SPACE = UTF-8 E2 80 89
@@ -38,13 +39,13 @@ public:
/** Bitcoin units.
@note Source: https://en.bitcoin.it/wiki/Units . Please add only sensible ones
*/
- enum Unit
- {
+ enum class Unit {
BTC,
mBTC,
uBTC,
SAT
};
+ Q_ENUM(Unit)
enum class SeparatorStyle
{
@@ -59,30 +60,28 @@ public:
//! Get list of units, for drop-down box
static QList<Unit> availableUnits();
- //! Is unit ID valid?
- static bool valid(int unit);
//! Long name
- static QString longName(int unit);
+ static QString longName(Unit unit);
//! Short name
- static QString shortName(int unit);
+ static QString shortName(Unit unit);
//! Longer description
- static QString description(int unit);
+ static QString description(Unit unit);
//! Number of Satoshis (1e-8) per unit
- static qint64 factor(int unit);
+ static qint64 factor(Unit unit);
//! Number of decimals left
- static int decimals(int unit);
+ static int decimals(Unit unit);
//! Format as string
- static QString format(int unit, const CAmount& amount, bool plussign = false, SeparatorStyle separators = SeparatorStyle::STANDARD, bool justify = false);
+ static QString format(Unit unit, const CAmount& amount, bool plussign = false, SeparatorStyle separators = SeparatorStyle::STANDARD, bool justify = false);
//! Format as string (with unit)
- static QString formatWithUnit(int unit, const CAmount& amount, bool plussign=false, SeparatorStyle separators=SeparatorStyle::STANDARD);
+ static QString formatWithUnit(Unit unit, const CAmount& amount, bool plussign = false, SeparatorStyle separators = SeparatorStyle::STANDARD);
//! Format as HTML string (with unit)
- static QString formatHtmlWithUnit(int unit, const CAmount& amount, bool plussign=false, SeparatorStyle separators=SeparatorStyle::STANDARD);
+ static QString formatHtmlWithUnit(Unit unit, const CAmount& amount, bool plussign = false, SeparatorStyle separators = SeparatorStyle::STANDARD);
//! Format as string (with unit) of fixed length to preserve privacy, if it is set.
- static QString formatWithPrivacy(int unit, const CAmount& amount, SeparatorStyle separators, bool privacy);
+ static QString formatWithPrivacy(Unit unit, const CAmount& amount, SeparatorStyle separators, bool privacy);
//! Parse string to coin amount
- static bool parse(int unit, const QString &value, CAmount *val_out);
+ static bool parse(Unit unit, const QString& value, CAmount* val_out);
//! Gets title for amount column including current display unit if optionsModel reference available */
- static QString getAmountColumnTitle(int unit);
+ static QString getAmountColumnTitle(Unit unit);
///@}
//! @name AbstractListModel implementation
@@ -107,8 +106,11 @@ public:
static CAmount maxMoney();
private:
- QList<BitcoinUnits::Unit> unitlist;
+ QList<Unit> unitlist;
};
typedef BitcoinUnits::Unit BitcoinUnit;
+QDataStream& operator<<(QDataStream& out, const BitcoinUnit& unit);
+QDataStream& operator>>(QDataStream& in, BitcoinUnit& unit);
+
#endif // BITCOIN_QT_BITCOINUNITS_H
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index 07c3e62a03..bd9a90a890 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -507,7 +507,7 @@ void CoinControlDialog::updateLabels(CCoinControl& m_coin_control, WalletModel *
}
// actually update labels
- int nDisplayUnit = BitcoinUnits::BTC;
+ BitcoinUnit nDisplayUnit = BitcoinUnit::BTC;
if (model && model->getOptionsModel())
nDisplayUnit = model->getOptionsModel()->getDisplayUnit();
@@ -590,7 +590,7 @@ void CoinControlDialog::updateView()
QFlags<Qt::ItemFlag> flgCheckbox = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
QFlags<Qt::ItemFlag> flgTristate = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsAutoTristate;
- int nDisplayUnit = model->getOptionsModel()->getDisplayUnit();
+ BitcoinUnit nDisplayUnit = model->getOptionsModel()->getDisplayUnit();
for (const auto& coins : model->wallet().listCoins()) {
CCoinControlWidgetItem* itemWalletAddress{nullptr};
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index ca0b8c20f0..6fb5fce5b3 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -178,8 +178,7 @@ bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out)
{
if(!i->second.isEmpty())
{
- if(!BitcoinUnits::parse(BitcoinUnits::BTC, i->second, &rv.amount))
- {
+ if (!BitcoinUnits::parse(BitcoinUnit::BTC, i->second, &rv.amount)) {
return false;
}
}
@@ -211,7 +210,7 @@ QString formatBitcoinURI(const SendCoinsRecipient &info)
if (info.amount)
{
- ret += QString("?amount=%1").arg(BitcoinUnits::format(BitcoinUnits::BTC, info.amount, false, BitcoinUnits::SeparatorStyle::NEVER));
+ ret += QString("?amount=%1").arg(BitcoinUnits::format(BitcoinUnit::BTC, info.amount, false, BitcoinUnits::SeparatorStyle::NEVER));
paramCount++;
}
diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp
index 52bda59748..40b9ed5483 100644
--- a/src/qt/optionsmodel.cpp
+++ b/src/qt/optionsmodel.cpp
@@ -24,6 +24,7 @@
#include <QLatin1Char>
#include <QSettings>
#include <QStringList>
+#include <QVariant>
const char *DEFAULT_GUI_PROXY_HOST = "127.0.0.1";
@@ -71,9 +72,16 @@ void OptionsModel::Init(bool resetSettings)
fMinimizeOnClose = settings.value("fMinimizeOnClose").toBool();
// Display
- if (!settings.contains("nDisplayUnit"))
- settings.setValue("nDisplayUnit", BitcoinUnits::BTC);
- nDisplayUnit = settings.value("nDisplayUnit").toInt();
+ if (!settings.contains("DisplayBitcoinUnit")) {
+ settings.setValue("DisplayBitcoinUnit", QVariant::fromValue(BitcoinUnit::BTC));
+ }
+ QVariant unit = settings.value("DisplayBitcoinUnit");
+ if (unit.canConvert<BitcoinUnit>()) {
+ m_display_bitcoin_unit = unit.value<BitcoinUnit>();
+ } else {
+ m_display_bitcoin_unit = BitcoinUnit::BTC;
+ settings.setValue("DisplayBitcoinUnit", QVariant::fromValue(m_display_bitcoin_unit));
+ }
if (!settings.contains("strThirdPartyTxUrls"))
settings.setValue("strThirdPartyTxUrls", "");
@@ -376,7 +384,7 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const
return m_sub_fee_from_amount;
#endif
case DisplayUnit:
- return nDisplayUnit;
+ return QVariant::fromValue(m_display_bitcoin_unit);
case ThirdPartyTxUrls:
return strThirdPartyTxUrls;
case Language:
@@ -584,16 +592,13 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
return successful;
}
-/** Updates current unit in memory, settings and emits displayUnitChanged(newUnit) signal */
-void OptionsModel::setDisplayUnit(const QVariant &value)
+void OptionsModel::setDisplayUnit(const QVariant& new_unit)
{
- if (!value.isNull())
- {
- QSettings settings;
- nDisplayUnit = value.toInt();
- settings.setValue("nDisplayUnit", nDisplayUnit);
- Q_EMIT displayUnitChanged(nDisplayUnit);
- }
+ if (new_unit.isNull() || new_unit.value<BitcoinUnit>() == m_display_bitcoin_unit) return;
+ m_display_bitcoin_unit = new_unit.value<BitcoinUnit>();
+ QSettings settings;
+ settings.setValue("DisplayBitcoinUnit", QVariant::fromValue(m_display_bitcoin_unit));
+ Q_EMIT displayUnitChanged(m_display_bitcoin_unit);
}
void OptionsModel::setRestartRequired(bool fRequired)
diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h
index bb9a8c1f8c..510ebb5cfd 100644
--- a/src/qt/optionsmodel.h
+++ b/src/qt/optionsmodel.h
@@ -6,6 +6,7 @@
#define BITCOIN_QT_OPTIONSMODEL_H
#include <cstdint>
+#include <qt/bitcoinunits.h>
#include <qt/guiconstants.h>
#include <QAbstractListModel>
@@ -55,7 +56,7 @@ public:
ProxyUseTor, // bool
ProxyIPTor, // QString
ProxyPortTor, // int
- DisplayUnit, // BitcoinUnits::Unit
+ DisplayUnit, // BitcoinUnit
ThirdPartyTxUrls, // QString
Language, // QString
UseEmbeddedMonospacedFont, // bool
@@ -79,14 +80,14 @@ public:
int rowCount(const QModelIndex & parent = QModelIndex()) const override;
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole) override;
- /** Updates current unit in memory, settings and emits displayUnitChanged(newUnit) signal */
- void setDisplayUnit(const QVariant &value);
+ /** Updates current unit in memory, settings and emits displayUnitChanged(new_unit) signal */
+ void setDisplayUnit(const QVariant& new_unit);
/* Explicit getters */
bool getShowTrayIcon() const { return m_show_tray_icon; }
bool getMinimizeToTray() const { return fMinimizeToTray; }
bool getMinimizeOnClose() const { return fMinimizeOnClose; }
- int getDisplayUnit() const { return nDisplayUnit; }
+ BitcoinUnit getDisplayUnit() const { return m_display_bitcoin_unit; }
QString getThirdPartyTxUrls() const { return strThirdPartyTxUrls; }
bool getUseEmbeddedMonospacedFont() const { return m_use_embedded_monospaced_font; }
bool getCoinControlFeatures() const { return fCoinControlFeatures; }
@@ -112,7 +113,7 @@ private:
bool fMinimizeToTray;
bool fMinimizeOnClose;
QString language;
- int nDisplayUnit;
+ BitcoinUnit m_display_bitcoin_unit;
QString strThirdPartyTxUrls;
bool m_use_embedded_monospaced_font;
bool fCoinControlFeatures;
@@ -127,7 +128,7 @@ private:
// Check settings version and upgrade default values if required
void checkAndMigrate();
Q_SIGNALS:
- void displayUnitChanged(int unit);
+ void displayUnitChanged(BitcoinUnit unit);
void coinControlFeaturesChanged(bool);
void showTrayIconChanged(bool);
void useEmbeddedMonospacedFontChanged(bool);
diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp
index 7127706463..820bcbf3cd 100644
--- a/src/qt/overviewpage.cpp
+++ b/src/qt/overviewpage.cpp
@@ -34,9 +34,9 @@ class TxViewDelegate : public QAbstractItemDelegate
{
Q_OBJECT
public:
- explicit TxViewDelegate(const PlatformStyle *_platformStyle, QObject *parent=nullptr):
- QAbstractItemDelegate(parent), unit(BitcoinUnits::BTC),
- platformStyle(_platformStyle)
+ explicit TxViewDelegate(const PlatformStyle* _platformStyle, QObject* parent = nullptr)
+ : QAbstractItemDelegate(parent), unit(BitcoinUnit::BTC),
+ platformStyle(_platformStyle)
{
connect(this, &TxViewDelegate::width_changed, this, &TxViewDelegate::sizeHintChanged);
}
@@ -125,7 +125,7 @@ public:
return {DECORATION_SIZE + 8 + minimum_text_width, DECORATION_SIZE};
}
- int unit;
+ BitcoinUnit unit;
Q_SIGNALS:
//! An intermediate signal for emitting from the `paint() const` member function.
@@ -197,7 +197,7 @@ OverviewPage::~OverviewPage()
void OverviewPage::setBalance(const interfaces::WalletBalances& balances)
{
- int unit = walletModel->getOptionsModel()->getDisplayUnit();
+ BitcoinUnit unit = walletModel->getOptionsModel()->getDisplayUnit();
m_balances = balances;
if (walletModel->wallet().isLegacy()) {
if (walletModel->wallet().privateKeysDisabled()) {
diff --git a/src/qt/psbtoperationsdialog.cpp b/src/qt/psbtoperationsdialog.cpp
index 6880c157c0..333766ce21 100644
--- a/src/qt/psbtoperationsdialog.cpp
+++ b/src/qt/psbtoperationsdialog.cpp
@@ -181,7 +181,7 @@ std::string PSBTOperationsDialog::renderTransaction(const PartiallySignedTransac
ExtractDestination(out.scriptPubKey, address);
totalAmount += out.nValue;
tx_description.append(tr(" * Sends %1 to %2")
- .arg(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, out.nValue))
+ .arg(BitcoinUnits::formatWithUnit(BitcoinUnit::BTC, out.nValue))
.arg(QString::fromStdString(EncodeDestination(address))));
tx_description.append("<br>");
}
@@ -193,7 +193,7 @@ std::string PSBTOperationsDialog::renderTransaction(const PartiallySignedTransac
tx_description.append(tr("Unable to calculate transaction fee or total transaction amount."));
} else {
tx_description.append(tr("Pays transaction fee: "));
- tx_description.append(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, *analysis.fee));
+ tx_description.append(BitcoinUnits::formatWithUnit(BitcoinUnit::BTC, *analysis.fee));
// add total amount in all subdivision units
tx_description.append("<hr />");
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index c924789796..fd8eccb86d 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -380,8 +380,7 @@ bool SendCoinsDialog::PrepareSendText(QString& question_string, QString& informa
question_string.append("<hr />");
CAmount totalAmount = m_current_transaction->getTotalTransactionAmount() + txFee;
QStringList alternativeUnits;
- for (const BitcoinUnits::Unit u : BitcoinUnits::availableUnits())
- {
+ for (const BitcoinUnit u : BitcoinUnits::availableUnits()) {
if(u != model->getOptionsModel()->getDisplayUnit())
alternativeUnits.append(BitcoinUnits::formatHtmlWithUnit(u, totalAmount));
}
diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp
index 6ab534764b..c4cd0f4cd1 100644
--- a/src/qt/test/wallettests.cpp
+++ b/src/qt/test/wallettests.cpp
@@ -7,24 +7,25 @@
#include <interfaces/chain.h>
#include <interfaces/node.h>
+#include <key_io.h>
#include <qt/bitcoinamountfield.h>
+#include <qt/bitcoinunits.h>
#include <qt/clientmodel.h>
#include <qt/optionsmodel.h>
+#include <qt/overviewpage.h>
#include <qt/platformstyle.h>
#include <qt/qvalidatedlineedit.h>
+#include <qt/receivecoinsdialog.h>
+#include <qt/receiverequestdialog.h>
+#include <qt/recentrequeststablemodel.h>
#include <qt/sendcoinsdialog.h>
#include <qt/sendcoinsentry.h>
#include <qt/transactiontablemodel.h>
#include <qt/transactionview.h>
#include <qt/walletmodel.h>
-#include <key_io.h>
#include <test/util/setup_common.h>
#include <validation.h>
#include <wallet/wallet.h>
-#include <qt/overviewpage.h>
-#include <qt/receivecoinsdialog.h>
-#include <qt/recentrequeststablemodel.h>
-#include <qt/receiverequestdialog.h>
#include <chrono>
#include <memory>
@@ -196,7 +197,7 @@ void TestGUI(interfaces::Node& node)
// Check balance in send dialog
QLabel* balanceLabel = sendCoinsDialog.findChild<QLabel*>("labelBalance");
QString balanceText = balanceLabel->text();
- int unit = walletModel.getOptionsModel()->getDisplayUnit();
+ BitcoinUnit unit = walletModel.getOptionsModel()->getDisplayUnit();
CAmount balance = walletModel.wallet().getBalance();
QString balanceComparison = BitcoinUnits::formatWithUnit(unit, balance, false, BitcoinUnits::SeparatorStyle::ALWAYS);
QCOMPARE(balanceText, balanceComparison);
@@ -222,7 +223,7 @@ void TestGUI(interfaces::Node& node)
overviewPage.setWalletModel(&walletModel);
QLabel* balanceLabel = overviewPage.findChild<QLabel*>("labelBalance");
QString balanceText = balanceLabel->text().trimmed();
- int unit = walletModel.getOptionsModel()->getDisplayUnit();
+ BitcoinUnit unit = walletModel.getOptionsModel()->getDisplayUnit();
CAmount balance = walletModel.wallet().getBalance();
QString balanceComparison = BitcoinUnits::formatWithUnit(unit, balance, false, BitcoinUnits::SeparatorStyle::ALWAYS);
QCOMPARE(balanceText, balanceComparison);
diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp
index be5851d627..9e92f89543 100644
--- a/src/qt/transactiondesc.cpp
+++ b/src/qt/transactiondesc.cpp
@@ -32,20 +32,18 @@ using wallet::ISMINE_SPENDABLE;
using wallet::ISMINE_WATCH_ONLY;
using wallet::isminetype;
-QString TransactionDesc::FormatTxStatus(const interfaces::WalletTx& wtx, const interfaces::WalletTxStatus& status, bool inMempool, int numBlocks)
+QString TransactionDesc::FormatTxStatus(const interfaces::WalletTxStatus& status, bool inMempool)
{
- {
- int nDepth = status.depth_in_main_chain;
- if (nDepth < 0) {
- return tr("conflicted with a transaction with %1 confirmations").arg(-nDepth);
- } else if (nDepth == 0) {
- const QString abandoned{status.is_abandoned ? QLatin1String(", ") + tr("abandoned") : QString()};
- return tr("0/unconfirmed, %1").arg(inMempool ? tr("in memory pool") : tr("not in memory pool")) + abandoned;
- } else if (nDepth < 6) {
- return tr("%1/unconfirmed").arg(nDepth);
- } else {
- return tr("%1 confirmations").arg(nDepth);
- }
+ int depth = status.depth_in_main_chain;
+ if (depth < 0) {
+ return tr("conflicted with a transaction with %1 confirmations").arg(-depth);
+ } else if (depth == 0) {
+ const QString abandoned{status.is_abandoned ? QLatin1String(", ") + tr("abandoned") : QString()};
+ return tr("0/unconfirmed, %1").arg(inMempool ? tr("in memory pool") : tr("not in memory pool")) + abandoned;
+ } else if (depth < 6) {
+ return tr("%1/unconfirmed").arg(depth);
+ } else {
+ return tr("%1 confirmations").arg(depth);
}
}
@@ -77,7 +75,7 @@ bool GetPaymentRequestMerchant(const std::string& pr, QString& merchant)
return false;
}
-QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wallet, TransactionRecord *rec, int unit)
+QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wallet, TransactionRecord* rec, BitcoinUnit unit)
{
int numBlocks;
interfaces::WalletTxStatus status;
@@ -95,7 +93,7 @@ QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wall
CAmount nDebit = wtx.debit;
CAmount nNet = nCredit - nDebit;
- strHTML += "<b>" + tr("Status") + ":</b> " + FormatTxStatus(wtx, status, inMempool, numBlocks);
+ strHTML += "<b>" + tr("Status") + ":</b> " + FormatTxStatus(status, inMempool);
strHTML += "<br>";
strHTML += "<b>" + tr("Date") + ":</b> " + (nTime ? GUIUtil::dateTimeStr(nTime) : "") + "<br>";
diff --git a/src/qt/transactiondesc.h b/src/qt/transactiondesc.h
index cf955a433c..803e41b699 100644
--- a/src/qt/transactiondesc.h
+++ b/src/qt/transactiondesc.h
@@ -5,6 +5,8 @@
#ifndef BITCOIN_QT_TRANSACTIONDESC_H
#define BITCOIN_QT_TRANSACTIONDESC_H
+#include <qt/bitcoinunits.h>
+
#include <QObject>
#include <QString>
@@ -24,12 +26,12 @@ class TransactionDesc: public QObject
Q_OBJECT
public:
- static QString toHTML(interfaces::Node& node, interfaces::Wallet& wallet, TransactionRecord *rec, int unit);
+ static QString toHTML(interfaces::Node& node, interfaces::Wallet& wallet, TransactionRecord* rec, BitcoinUnit unit);
private:
TransactionDesc() {}
- static QString FormatTxStatus(const interfaces::WalletTx& wtx, const interfaces::WalletTxStatus& status, bool inMempool, int numBlocks);
+ static QString FormatTxStatus(const interfaces::WalletTxStatus& status, bool inMempool);
};
#endif // BITCOIN_QT_TRANSACTIONDESC_H
diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h
index dd34656d5f..d8748d7dc9 100644
--- a/src/qt/transactionrecord.h
+++ b/src/qt/transactionrecord.h
@@ -20,13 +20,7 @@ struct WalletTxStatus;
/** UI model for transaction status. The transaction status is the part of a transaction that will change over time.
*/
-class TransactionStatus
-{
-public:
- TransactionStatus() : countsForBalance(false), sortKey(""),
- matures_in(0), status(Unconfirmed), depth(0), open_for(0)
- { }
-
+struct TransactionStatus {
enum Status {
Confirmed, /**< Have 6 or more confirmations (normal tx) or fully mature (mined tx) **/
/// Normal (sent/received) transactions
@@ -40,28 +34,25 @@ public:
};
/// Transaction counts towards available balance
- bool countsForBalance;
+ bool countsForBalance{false};
/// Sorting key based on status
std::string sortKey;
/** @name Generated (mined) transactions
@{*/
- int matures_in;
+ int matures_in{0};
/**@}*/
/** @name Reported status
@{*/
- Status status;
- qint64 depth;
- qint64 open_for; /**< Timestamp if status==OpenUntilDate, otherwise number
- of additional blocks that need to be mined before
- finalization */
+ Status status{Unconfirmed};
+ qint64 depth{0};
/**@}*/
/** Current block hash (to know whether cached status is still valid) */
uint256 m_cur_block_hash{};
- bool needsUpdate;
+ bool needsUpdate{false};
};
/** UI model for a transaction. A core transaction can be represented by multiple UI transactions if it has
diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp
index 6b0495f5a8..7b932890cf 100644
--- a/src/qt/transactiontablemodel.cpp
+++ b/src/qt/transactiontablemodel.cpp
@@ -5,6 +5,7 @@
#include <qt/transactiontablemodel.h>
#include <qt/addresstablemodel.h>
+#include <qt/bitcoinunits.h>
#include <qt/clientmodel.h>
#include <qt/guiconstants.h>
#include <qt/guiutil.h>
@@ -232,7 +233,7 @@ public:
return nullptr;
}
- QString describe(interfaces::Node& node, interfaces::Wallet& wallet, TransactionRecord *rec, int unit)
+ QString describe(interfaces::Node& node, interfaces::Wallet& wallet, TransactionRecord* rec, BitcoinUnit unit)
{
return TransactionDesc::toHTML(node, wallet, rec, unit);
}
diff --git a/src/qt/walletview.h b/src/qt/walletview.h
index 2f9d344bc8..301084ffa9 100644
--- a/src/qt/walletview.h
+++ b/src/qt/walletview.h
@@ -6,6 +6,7 @@
#define BITCOIN_QT_WALLETVIEW_H
#include <consensus/amount.h>
+#include <qt/bitcoinunits.h>
#include <QStackedWidget>
@@ -115,7 +116,7 @@ Q_SIGNALS:
/** Encryption status of wallet changed */
void encryptionStatusChanged();
/** Notify that a new transaction appeared */
- void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label, const QString& walletName);
+ void incomingTransaction(const QString& date, BitcoinUnit unit, const CAmount& amount, const QString& type, const QString& address, const QString& label, const QString& walletName);
/** Notify that the out of sync warning icon has been pressed */
void outOfSyncWarningClicked();
};
diff --git a/src/random.cpp b/src/random.cpp
index b862510524..77d2ae4d43 100644
--- a/src/random.cpp
+++ b/src/random.cpp
@@ -13,7 +13,7 @@
#include <compat.h> // for Windows API
#include <wincrypt.h>
#endif
-#include <logging.h> // for LogPrintf()
+#include <logging.h>
#include <randomenv.h>
#include <support/allocators/secure.h>
#include <sync.h> // for Mutex
diff --git a/src/sync.h b/src/sync.h
index af7595e6fa..c69b58741b 100644
--- a/src/sync.h
+++ b/src/sync.h
@@ -223,12 +223,12 @@ public:
friend class reverse_lock;
};
-#define REVERSE_LOCK(g) typename std::decay<decltype(g)>::type::reverse_lock PASTE2(revlock, __COUNTER__)(g, #g, __FILE__, __LINE__)
+#define REVERSE_LOCK(g) typename std::decay<decltype(g)>::type::reverse_lock UNIQUE_NAME(revlock)(g, #g, __FILE__, __LINE__)
template<typename MutexArg>
using DebugLock = UniqueLock<typename std::remove_reference<typename std::remove_pointer<MutexArg>::type>::type>;
-#define LOCK(cs) DebugLock<decltype(cs)> PASTE2(criticalblock, __COUNTER__)(cs, #cs, __FILE__, __LINE__)
+#define LOCK(cs) DebugLock<decltype(cs)> UNIQUE_NAME(criticalblock)(cs, #cs, __FILE__, __LINE__)
#define LOCK2(cs1, cs2) \
DebugLock<decltype(cs1)> criticalblock1(cs1, #cs1, __FILE__, __LINE__); \
DebugLock<decltype(cs2)> criticalblock2(cs2, #cs2, __FILE__, __LINE__);
diff --git a/src/test/data/key_io_invalid.json b/src/test/data/key_io_invalid.json
index abe07dad24..8f55abfec7 100644
--- a/src/test/data/key_io_invalid.json
+++ b/src/test/data/key_io_invalid.json
@@ -6,207 +6,207 @@
"x"
],
[
- "2v7k5Bb8Lr1MMgTgW6HAf5YHXi6BzpPjHpQ4srD4RSwHYpzXKiXmLAgiLhkXvp3JF5v7nq45EWr"
+ "1GAdfviErV2Ew95FPtZyikz2qGP3gyCB6Hyu94sedAkPpA523m3fQwps9YKUZkKgQckGPKhRsFR"
],
[
- "RAZzCGtMbiUgMiiyrZySrSpdfnQReFXA3r"
+ "37G2kMDLpmWVhimxRdzwNfE8JFvWXnJYnVcXeeGrek2qumdJuK7XArcVVpRtLLjRra3t64BEPF2"
],
[
- "NYamy7tcPQTzoU5iyQojD3sqhiz7zxkvn8"
+ "giymtio7u7oqWtmC9YnvAEKkLF3JQpAdkEFkVJKYrVDfaLbhaDpX1ihfF2vZmya1i61fwLPC3YQ"
],
[
- "geaFG555Ex5nyRf7JjW6Pj2GwZA8KYxtJJLbr1eZhVW75STbYBZeRszy3wg4pkKdF4ez9J4wQiz"
+ "8iVk9nLM3nYwRuwypjy9NK5rsuZH7BbrQRZ1pgcQmvMnjAgRXD"
],
[
- "2Cxmid3c2XQ2zvQ8SA1ha2TKqvqbJS9XFmXRsCneBS3Po7Qqb65z5zNdsoF9AfieXFcpoVPmkmfa"
+ "cPTVQ1hbo4qdoysf6Jx5GthqucNmdfqt6J2pZRFeXv8Ep7Kmjqud"
],
[
- "gaJ7UVge2njVg9tFTetJrtHgruMm7aQDiSAxfHrVEgzK8N2ooagDVmDkdph434xzc4K96Gjyxcs"
+ "cQbR2Ny85XFBzUMx3Ed6HsTLw2pVruSgPvt5AofnBUnhiv86gYeW"
],
[
- "5JN5BEVQPZ3tAiatz1RGXkrJuE3EC6bervMaPb38wTNgEuZCeqp"
+ "2UB3iG3VJbX2TRrMwm6ssWskgvU9VjFBYSqCzwqkrihCwo7mg4mtS4WuGZgxTKuxf5A3EcotYEymz"
],
[
- "3TnFbyUtBRS5rE1KTW81qLVspjJNaB3uu6uuvLjxhZo2DB6PCGh"
+ "cQe12pqwPR6ExtZKfrKf1q4b3CTh1Qi7MwuvMvzs79nWXDvESfBJ"
],
[
- "7UgSZGaMaTc4d2mdEgcGBFiMeS6eMsithGUqvBsKTQdGzD7XQDbMEYo3gojdbXEPbUdFF3CQoK72f"
+ "tc1qeul5g2xfkvdkrhcfmdursv73ad64jnkjl9c40f"
],
[
- "9261wfqQqruNDnBDhbbb4tN9oKA1KpRFHeoYeufyJApVGixyAG4V"
+ "bt1pq65rzej5glw3ra79gav6fqnx4haa0z257qr3mc8cggkefahmgvyseufhc0"
],
[
- "cS824CTUh18scFmYuqt6BgxuRhdR4dEEnCHs3fzBbcyQgbfasHbw"
+ "tb13hty4qmumlwpp6chxjvcyzza4duqgtmxw3xhm3u9ahj4nyhtwz8eq7ynrj4"
],
[
- "tc1q0ywf7wkz6t580n3yemd3ucfw8jxn93tpc6wskt"
+ "bcrt1r2qxpwuge"
],
[
- "bt1pxeeuh96wpm5c6u3kavts2qgwlv6y8um7u7ga6ltlwrhrv7w9vers8lgt3k"
+ "bc10uexgzna2dpfk0vjt35srz6a27ps6m0l89jweznt83n2sqn2fx4hvn9ym5af8wut34sfrqhk3"
],
[
- "tb130lvl2lyugsk2tf3zhwcjjv39dmwt2tt7ytqaexy8edwcuwks6p5scll5kz"
+ "tb1qum6uh0pt4q253qaf520929737v63w5gf"
],
[
- "bcrt1rhsveeudk"
+ "bcrt1q888ryfgxpvl0k7vum8zpyar2u2sexvdhkf38ue37yknmqq0ycrwpl3w48y"
],
[
- "bc10rmfwl8nxdweeyc4sf89t0tn9fv9w6qpyzsnl2r4k48vjqh03qas9asdje0rlr0phru0wqw0p"
+ "bc1qdsuzmn04k2z8vryw8l4dj8m5ygqgnne5n"
],
[
- "tb1qjqnfsuatr54e957xzg9sqk7yqcry9lns"
+ "tb1qlj8es50nc8j8r8xshrjgzmw5azx89efghmw8ju6zcqla0g6xcnrstsjz7k"
],
[
- "bcrt1q8p08mv8echkf3es027u4cdswxlylm3th76ls8v6y4zy4vwsavngpr4e4td"
+ "bcrt1qzwmyj0z924g7fzs5yvnrkc43y76RVyr2lh5t4r"
],
[
- "BC1QNC2H66VLWTWTW52DP0FYUSNU3QQG5VT4V"
+ "bc1qpu6d26mrulzetu4jqhd7rsunv9aqru26f5c4j8"
],
[
- "tb1qgk665m2auw09rc7pqyf7aulcuhmatz9xqtr5mxew7zuysacaascqs9v0vn"
+ "tb1qun6d26ufh77ghny6u5u8cwz9da7qwc6k4wkuceae9tth06eqlw0syupl4w"
],
[
- "bcrt17CAPP7"
+ "bcrt1qj7g2jps453kj9htk9cxyyc2nxe69x4kzzmth7v"
],
[
- "bc1qxmf2d6aerjzam3rur0zufqxqnyqfts5u302s7x"
+ "bc1p702xksx4z3uqf0u2phllxkfe5cgu0adxptqs0uelx0tqt8e885sqryes2l"
],
[
- "tb1qn8x5dnzpexq7nnvrvnhwr9c3wkakpcyu9wwsjzq9pstkwg0t6qhs4l3rv6"
+ "tb1z7gmh0v6pc30z4xum76lmw8w86yswrlmw"
],
[
- "BCRT1Q397G2RNVYRL5LK07CE8NCKHVKP8Z4SC9U0MVH9"
+ "bcrt1sjsrw6nun4h502cr97xmnyyuhkr22q0s6efrgtu"
],
[
- "bc1pgxwyajq0gdn389f69uwn2fw9q0z5c9s063j5dgkdd23ajaud4hpsercr9h"
+ "2UVPFpGYnLHJezFzjUo42our6PMEoozzRdM"
],
[
- "tb1z6mnmp5k542l6yk4ul0mp4rq3yvz44lfm"
+ "2MygHQjE1U33q3LSC53p69YqFjP8PihumJAF"
],
[
- "bcrt17capp7"
+ "KzNbAQ4mexfAxa6RKBzHQqfoTycaeWpv2p"
],
[
- "2D2bqvKseKHdoKjCNvjVULUgmxHu9hjKGwDbPRjTRH59tsHNLeyKwq3vyVBbo9LByY9wiapqjwFY"
+ "2jDPrDfAKihCGPbPD9ztY8TswAia4V8Bc6vx"
],
[
- "2SSjAim4wZpeQRe5zTj1qqS6Li9ttJDaZ3ze"
+ "4VQUNG1hG64QFtaNyQZQWDdwpxB275Pwb3tvyPt2HDxB8Mi2MgH8Tz3AC83YYiz9LydsLNXEZJLHY"
],
[
- "mi9H6MjLwXxy9kxe1x4ToxyLRBsmcZxgVi"
+ "39TKsUQ5QpEL1wowc6GMUqak94ijirPuP69ooV3xsFmiKQX2dau"
],
[
- "VciXoxEitcn88jy197J9n9cpJ1pZahzU3SyWUiHqLgcfjttLEEJz"
+ "2UEJjT3dSdwc8dAo7oedPzznXceXCEsBbDfAvSymqpqDrkZMv7JBEUpLyhkghioYAWC9W4sKysry"
],
[
- "KppmwADGoExPT9Eq5hjRWpWFDbzJyfzHFgsfxBiDHNpVBgWPRNuy"
+ "7VmMEkphxCFSV1y659Th4dkk6x6bJS5eQvbt8rzUYKQyd6ACgwQ4vXHtXKFUwP2kW3XULipnHJdZ7"
],
[
- "TN7EQXMxKffzvHo54yHHu9R4ks9f5gWBW3MMVf5k72zAqrgVK9ys"
+ "tc1qdlapns4zkn03juf2k9xwwpct209suj6mgcd9gh"
],
[
- "92dbrMEYzP5dD5UhQ6maNkCQ4GLG42BM4Gc6XKZzSSMSfosfkkcB"
+ "bt1psa5eptk29c4jc9yumeseat3a0l5e2fpmw635za2p4gpwdnthueysxga9je"
],
[
- "J7VQxPxyzuWEkRstQWpCz2AgysEz1APgnWCEQrFvkN3umAnCrhQF"
+ "tb13w8c43lykfj3lvm9sgp6dsnfjla3d57cm83seykunf0ltxjc9lt2q4efm4d"
],
[
- "tc1qymllj6c96v5qj2504y27ldtner6eh8ldx38t83"
+ "bcrt1rjqr2tdkm"
],
[
- "bt1flep4g"
+ "bc10lyxwnxa70l270e6fcmxr4x7dtgu2yvy7gzkurwxy4zhdvgaqrrn6pfg2flyhqzy5t5se8yu3"
],
[
- "tb13c553hwygcgj48qwmr9f8q0hgdcfklyaye5sxzcpcjnmxv4z506xs90tchn"
+ "TB1QFDFM763VXVSUNZHQLPWC0Q8FG5LJX6ZN"
],
[
- "bcrt1tyddyu"
+ "bcrt1q60chha7wfwlau4kdr4mlvyeyc8mnnh9dhxk05e0hmrxcuhghefj36uwyha"
],
[
- "bc10qssq2mknjqf0glwe2f3587wc4jysvs3f8s6chysae6hcl6fxzdm4wxyyscrl5k9f5qmnf05a"
+ "bc1gmk9yu"
],
[
- "tb1q425lmgvxdgtyl2m6xuu2pc354y4fvgg8"
+ "tb1ly0q7p"
],
[
- "bcrt1q9wp8e5d2u3u4g0pll0cy7smeeuqezdun9xl439n3p2gg4fvgfvk3hu52hj"
+ "bcrt1qdwttaw38uf42wxw40kwk3u8nguyTQH3hx6jmqp"
],
[
- "bc1qrz5acazpue8vl4zsaxn8fxtmeuqmyjkq3"
+ "bc1qtsvlht6730n04f2mpaj5vv8hrledn5n5ug8c79"
],
[
- "tb1qkeuglpgmnex9tv3fr7htzfrh3rwrk23r52rx9halxzmv9fr85lwq0fwhmp"
+ "tb1dclvmr"
],
[
- "bcrt1qd0t2wrhl7s57z99rsyaekpq0dyjcQRSSmz80r4"
+ "bcrt1q3fqvctqu48wsvggrt09vj0yk2gzzcscdp4h98u"
],
[
- "BC1QXLFDUCGX90T3E53PQCNKJ2PK25MSF3VLPMVY6T"
+ "bc1prklpq7tjcawg89cmwwqr3u5apwav36xa4zz56ady7crsllm6mpnqts7p86"
],
[
- "tb1qmycg4zszgnk34vaurx3cu8wpvteg9h40yq6cp52gt26gjel03t3su3x3xu"
+ "tb1zkm58zyhxz3ffkfgsyprflg543slsl4c4"
],
[
- "bcrt1q9hy58r4fnuxqzdqndpmq9pptc9nt2dw3rczf5e"
+ "bcrt1snzr5kaypnfhpnjanrhd20fhqcjxm3hfh7dw9fu"
],
[
- "BC1PA7682NAY6JQSLUWAJYTC0ERWTMW7A4RPWLNTUS32LCXWLHVKKKTQ2UL8CG"
+ "2GgnYKqBGuA2Mm5GnrPsMTZR81xPhNtgMYoFUZngZGiobhCuUpCaTriUHRcgFreEekNdPAR17q8d"
],
[
- "tb1z850dpxnwz2fzae5h2myatj4yvu6rq5xq"
+ "AZEah8d1EK362okRBS66e8SvdtYkrE8tsX"
],
[
- "bcrt1sp525pzjsmpqvcrawjreww36e9keg876skjvpwt"
+ "gep8xr77FyPW6zYP15RiV9W8nL6w2HyHB16cUDakfyDceMA6ZzUdhJjk2LPuLYHnLkBqkRTTi6z"
],
[
- "xcAvW5jurCpzSpLxBKEhCewCgwwuGhqJnC"
+ "2NDNP7GY59tTJPZTpbkprhM9SR99Nn5rUs7"
],
[
- "2Cvv8yp9kXbQt8EKh6Yma95yJ1uwYF9YKXuVhGJyu3dHGVsb2AVpTC62TFACZZ3KDNrALxR2CVNs"
+ "2Csgzy2T287YAjeU5tFtt1nPshBZAUFQi4WtgaWyZGKSBNnKXHy2Tmxo8QK4Mfdds977ShcDWC5o"
],
[
- "niUuL46hCuEVvkAzZKHvD746qbmLmzip9Pv3F6UZV14JxzEXBnTkVxCT4URapChJG6qAEgsZs6G"
+ "Kwjk3Vy6sdXMQDGWJzaWmqFxUNtWZCX1q4F4Kpt8jNNUoWJUUaTY"
],
[
- "2UHHgGfiipzvB8Eumnmvq6SowvrMJimjT3NwwG1839XEiUfwtpSdkUrseNsQuagXv21ce7aZu6yo"
+ "Svj8kk98bAS9V4L2crmxakbhmnPm3cJ1tJ4Je4yVzDreU8eSTFURS1SPYv5oWEQD8Q9VBDvx5uF"
],
[
- "8u9djKu4u6o3bsgeR4BKNnLK3akpo64FYzDAmA9239wKeshgF97"
+ "KNYsv6v9GtkGeD4WdQnBEJCrPKQm91PTxAbCfXr66LEd4JDmhPWC"
],
[
- "TC1QPAARXSLVMXHVRR0474LZXQYZWLGFZYPSFVL9E4"
+ "2UJ2H2xvAeXmFKfQwMyDoSdQTTPFMNCT3SsoUafBWKzoGP3NsUK1buEgQZG38viyD53jgMdpqfT7"
],
[
- "bt1pakek0n2267t9yaksxaczgr2syhv9y3xkx0wnsdwchfa6xkmjtvuqg3kgyr"
+ "6aLMfayKF4TW4ecn5SEc8FExpyJA2peKxYRGZhes6tQ4NTTzuGy"
],
[
- "tb13h83rtwq62udrhwpn87uely7cyxcjrj0azz6a4r3n9s87x5uj98ys6ufp83"
+ "7VP4FmcebU2thJns9MnXde7LWfuqR5vMizrAuUoq2GcJjzTyA4RHFcPVdZL8PLg1SbpSFdJrvLXoY5"
],
[
- "bcrt1rk5vw5qf2"
+ "tc1q5qdvt99uc92jyz663dtdpfpv6nr67ahmgwcpq2"
],
[
- "bc10d3rmtg62h747en5j6fju5g5qyvsransrkty6ghh96pu647wumctejlsngh9pf26cysrys2x2"
+ "bt1peu3ppd7x796sjjenp09r8cs22rhylqm9lhggk72qp8q22vzft0wq2a0x6j"
],
[
- "tb1qajuy2cdwqgmrzc7la85al5cwcq374tsp"
+ "tb1323z3lnz7dl3kd0nsuh6xy4he9almzl67anxgg3xdzkaxc9rwntlqdhdzd7"
],
[
- "bcrt1q3udxvj6x20chqh723mn064mzz65yr56ef00xk8czvu3jnx04ydapzk02s5"
+ "bcrt1r2gc42sky"
],
[
- "bc1qule2szwzyaq4qy0s3aa4mauucyqt6fewe"
+ "bc10fd889x4hd54tqu2ewg9t4hhft2wl7m6x50av4uswzw46xe6as0xmltfg7vrjfkvm459vld7w"
],
[
- "tb1ql0qny5vg9gh5tyzke6dw36px5ulkrp24x53x0pl2t5lpwrtejw3s2seej2"
+ "TB1QZY7V0F2AT3308YGGNGN66ULJTCN3RY6F"
],
[
- "bcrt17CAPP7"
+ "bcrt1qjg3cwht92znyw0l4r5rtctmls337nrc7g0ry9drjxmlecjd3atl3fake7c"
],
[
- "bc1qtvm6davyf725wfedc2d5mrgfewqgcrce8gjrpl"
+ "bc1qmgf8xt8xkecl79k04mma3lz34gqep7hg4"
],
[
- "tb1q5acjgtqrrw3an0dzavxxxzlex8k7aukjzjk9v2u4rmfdqxjphcyq7ge97e"
+ "TB1Q3F9WGNXE9ZMTTMDN5VKVKHYZ8Y0LCV72YV7V5LSXTJXEYHNHEHASLYL0TZ"
]
]
diff --git a/src/test/data/key_io_valid.json b/src/test/data/key_io_valid.json
index 5dee44c04b..c051f8b76b 100644
--- a/src/test/data/key_io_valid.json
+++ b/src/test/data/key_io_valid.json
@@ -1,71 +1,71 @@
[
[
- "1BShJZ8A5q53oJJfMJoEF1gfZCWdZqZwwD",
- "76a914728d4cc27d19707b0197cfcd7c412d43287864b588ac",
+ "1FsSia9rv4NeEwvJ2GvXrX7LyxYspbN2mo",
+ "76a914a31c06bd463e3923bc1aadbde48b16976c08071788ac",
{
"chain": "main",
"isPrivkey": false
}
],
[
- "3L1YkZjdeNSqaZcNKZFXQfyokx3zVYm7r6",
- "a914c8f37c3cc21561296ad81f4bec6b5de10ebc185187",
+ "36j4NfKv6Akva9amjWrLG6MuSQym1GuEmm",
+ "a914373b819a068f32b7a6b38b6b38729647cfde01c287",
{
"chain": "main",
"isPrivkey": false
}
],
[
- "mhJuoGLgnJC8gdBgBzEigsoyG4omQXejPT",
- "76a91413a92d1998e081354d36c13ce0c9dc04b865d40a88ac",
+ "mzK2FFDEhxqHcmrJw1ysqFkVyhUULo45hZ",
+ "76a914ce28b26c57472737f5c3561a1761185bd8589a4388ac",
{
"chain": "test",
"isPrivkey": false
}
],
[
- "2N5VpzKEuYvZJbmg6eUNGnfrrD1ir92FWGu",
- "a91486648cc2faaf05660e72c04c7a837bcc3e986f1787",
+ "2NC2hEhe28ULKAJkW5MjZ3jtTMJdvXmByvK",
+ "a914ce0bba75891ff9ec60148d4bd4a09ee2dc5c933187",
{
"chain": "test",
"isPrivkey": false
}
],
[
- "mtQueCtmAnP3E4aBHXCiFNEQAuPaLMuQNy",
- "76a9148d74ecd86c845baf9c6d4484d2d00e731b79e34788ac",
+ "mww4LvqtTMKvmeQvizPz2EQv26xTneWrbg",
+ "76a914b4110ba93ac54afc14da3bdd19614774a2d55d2988ac",
{
"chain": "signet",
"isPrivkey": false
}
],
[
- "2NEvWRTHjh89gV52fkperFtwzoFWQiQmiCh",
- "a914edc895152c67ccff0ba620bcc373b789ec68266f87",
+ "2N1r7aC69VHeE7yQJPDLi9T1PYq4wnwvjuT",
+ "a9145e5a35ab44b3efaea5129ba22b88ba3e2976614587",
{
"chain": "signet",
"isPrivkey": false
}
],
[
- "mngdx94qJFhSf7A7SAEgQSC9fQJuapujJp",
- "76a9144e9dba545455a80ce94c343d1cac9dec62cbf22288ac",
+ "n4fajahJrAuKbN7uNsKjLjQkz9Qn5ewJXQ",
+ "76a914fdeca3b08e38af53d7c4c60e3ad208ce5066441088ac",
{
"chain": "regtest",
"isPrivkey": false
}
],
[
- "2NBzRN3pV56k3JUvSHifaHyzjGHv7ZS9FZZ",
- "a914cd9da5642451273e5b6d088854cc1fad4a8d442187",
+ "2MxFajLApXpYk4VodBSZSt7rw8y4ryABkfA",
+ "a91436e9f191e0b75036a77f65e2eaa4752443233fbe87",
{
"chain": "regtest",
"isPrivkey": false
}
],
[
- "5KcrFZvJ2p4dM6QVUPu53cKXcCfozA1PJLHm1mNAxkDYhgThLu4",
- "ed6c796e2f62377410766214f55aa81ac9a6590ad7ed57c509c983bf648409ac",
+ "5JuW2AMDYu4xVwRG9DZW18VbzQrGcd5RCgb99sS6ehJsNQXu5b9",
+ "8f8943bf956de595665c38ffff23827e17c10cdc1c27a028caae6c9810626198",
{
"chain": "main",
"isCompressed": false,
@@ -73,8 +73,8 @@
}
],
[
- "L195WBrf2G3nCnun4CLxrb8XKk9LbCqH43THh4n4QrL5SzRzpq9j",
- "74f76c106e38d20514a99a86e4fe3bb28319e7dd2ad21dbc170cbb516a5358fa",
+ "L5nJeqKmpHp4P7F8ZYyjwc5a7P4d8EabuGAzfGJk7yC1BJyzNaEd",
+ "ff778740f88ddcf102aeb81daee289c044c4a4571c4b6f287400f4b8e0b843f8",
{
"chain": "main",
"isCompressed": true,
@@ -82,8 +82,8 @@
}
],
[
- "92z6HnMQR4tWqjfVA3UaUN5EuUMgoVMdCa5rZFYZfmgyD7wxYCw",
- "b8511e1d74549e305517d48a1d394d1be2cfa5d0f3c0d83f9f450316ffa01276",
+ "92ZdE5HoLafywnTBbzPxbvRmp75pSfzvdU3XaZGh1cToipgdHVh",
+ "80c32d81e91bdea04cd7a3819b32275fc3298af4c7ec87eb0099527d041ced5c",
{
"chain": "test",
"isCompressed": false,
@@ -91,8 +91,8 @@
}
],
[
- "cTPnaF52x4w4Tq6afPxRHux3wbYb86thS7S45A7r3oZc1AHTQ6Qm",
- "ad68c48d337181da125de9061933ececcdf7d917631af7d34f7e38082bff9a11",
+ "cV83kKisF3RQSvXbUCm9ox3kaz5JjEUBWcx8tNydfGJcyeUxuH47",
+ "e0fcd4ce4e3d0e3de091f21415bb7cd011fac288c42020a879f28c2a4387df9b",
{
"chain": "test",
"isCompressed": true,
@@ -100,8 +100,8 @@
}
],
[
- "924U35yFcYkxe2JXGmuhSRVaShGyhRDZx1ysPmw1sAHuszGMoxq",
- "3e8dfaf78d4f02b11d0b645648a4f3080d71d0d068979c47f7255c9a29eee01d",
+ "92QuSnywrhsV7WPZChTgSQA23uSmj9MCEEno1eRBDG9sg8M29cX",
+ "6cf636ed8ac1bab033b64f66feaba65f70e684731e3f39105605968d3a963801",
{
"chain": "signet",
"isCompressed": false,
@@ -109,8 +109,8 @@
}
],
[
- "cRy1qCf2LUesGPQagTkYwk2V3PyN2KCPKgxeg6k6KoJPzH7nrVjw",
- "82d4187690d6b59bcffda27dae52f2ecb87313cfc0904e0b674a27d906a65fde",
+ "cND53Dhp8eCZqG2ghe8YhSCGesXZ8fE5PGD1khrqNvEi4RBoXhEK",
+ "12b5a10f3a11e708dc5412833c47ab7c368a21b9efe19293793ec879ce683018",
{
"chain": "signet",
"isCompressed": true,
@@ -118,8 +118,8 @@
}
],
[
- "932NTcHK35Apf2C3K9Zv1ZdeZEmB1x7ZT2Ju3SjoEY6pUgUpT7H",
- "bd7dba24df9e003e145ae9b4862776413a0bb6fa5b4e42753397f2d9536e58a9",
+ "91mn1wYKEB1zyof1VFm8tMtocZx1oBrKKRCu9GCpgZvPmBLEJjp",
+ "18a86e5a6c6977ddba0daca7fba5190f67ba56ccdc1b3f31308972236c2e4776",
{
"chain": "regtest",
"isCompressed": false,
@@ -127,8 +127,8 @@
}
],
[
- "cNa75orYQ2oos52zCnMaS5PG6XbNZKc5LpGxTHacrxwWeX4WAK3E",
- "1d87e3c58b08766fea03598380ec8d59f8c88d5392bf683ab1088bd4caf073ee",
+ "cPisAUdLvqqAr6MYtXnrWvgvyUAwuNyuTvZkDGw6miPhZdaiSDNH",
+ "3fdfec1371cedcdb8c190ca6ff8ad603f817edc0d93c2a687c7b36dd66e70f2a",
{
"chain": "regtest",
"isCompressed": true,
@@ -136,8 +136,8 @@
}
],
[
- "bc1q5cuatynjmk4szh40mmunszfzh7zrc5xm9w8ccy",
- "0014a639d59272ddab015eafdef9380922bf843c50db",
+ "bc1qvyq0cc6rahyvsazfdje0twl7ez82ndmuac2lhv",
+ "00146100fc6343edc8c874496cb2f5bbfec88ea9b77c",
{
"chain": "main",
"isPrivkey": false,
@@ -145,8 +145,8 @@
}
],
[
- "bc1qkw7lz3ahms6e0ajv27mzh7g62tchjpmve4afc29u7w49tddydy2syv0087",
- "0020b3bdf147b7dc3597f64c57b62bf91a52f179076ccd7a9c28bcf3aa55b5a46915",
+ "bc1qyucykdlhp62tezs0hagqury402qwhk589q80tqs5myh3rxq34nwqhkdhv7",
+ "002027304b37f70e94bc8a0fbf500e0c957a80ebda87280ef58214d92f119811acdc",
{
"chain": "main",
"isPrivkey": false,
@@ -154,8 +154,8 @@
}
],
[
- "bc1p5rgvqejqh9dh37t9g94dd9cm8vtqns7dndgj423egwggsggcdzmsspvr7j",
- "5120a0d0c06640b95b78f965416ad6971b3b1609c3cd9b512aaa39439088211868b7",
+ "bc1p83n3au0rjylefxq2nc2xh2y4jzz4pm6zxj4mw5pagdjjr2a9f36s6jjnnu",
+ "51203c671ef1e3913f94980a9e146ba895908550ef4234abb7503d436521aba54c75",
{
"chain": "main",
"isPrivkey": false,
@@ -163,8 +163,8 @@
}
],
[
- "bc1zr4pq63udck",
- "52021d42",
+ "bc1z2rksukkjr8",
+ "520250ed",
{
"chain": "main",
"isPrivkey": false,
@@ -172,8 +172,8 @@
}
],
[
- "tb1q74fxwnvhsue0l8wremgq66xzvn48jlc5zthsvz",
- "0014f552674d978732ff9dc3ced00d68c264ea797f14",
+ "tb1qcrh3yqn4nlleplcez2yndq2ry8h9ncg3qh7n54",
+ "0014c0ef1202759fff90ff19128936814321ee59e111",
{
"chain": "test",
"isPrivkey": false,
@@ -181,8 +181,8 @@
}
],
[
- "tb1qpt7cqgq8ukv92dcraun9c3n0s3aswrt62vtv8nqmkfpa2tjfghesv9ln74",
- "00200afd802007e598553703ef265c466f847b070d7a5316c3cc1bb243d52e4945f3",
+ "tb1quyl9ujpgwr2chdzdnnalen48sup245vdfnh2jxhsuq3yx80rrwlq5hqfe4",
+ "0020e13e5e482870d58bb44d9cfbfccea78702aad18d4ceea91af0e022431de31bbe",
{
"chain": "test",
"isPrivkey": false,
@@ -190,8 +190,8 @@
}
],
[
- "tb1ph9v3e8nxct57hknlkhkz75p5pnxnkn05cw8ewpxu6tek56g29xgqydzfu7",
- "5120b9591c9e66c2e9ebda7fb5ec2f50340ccd3b4df4c38f9704dcd2f36a690a2990",
+ "tb1p35n52jy6xkm4wd905tdy8qtagrn73kqdz73xe4zxpvq9t3fp50aqk3s6gz",
+ "51208d2745489a35b75734afa2da43817d40e7e8d80d17a26cd4460b0055c521a3fa",
{
"chain": "test",
"isPrivkey": false,
@@ -199,8 +199,8 @@
}
],
[
- "tb1ray6e8gxfx49ers6c4c70l3c8lsxtcmlx",
- "5310e93593a0c9354b91c358ae3cffc707fc",
+ "tb1rgv5m6uvdk3kc7qsuz0c79v88ycr5w4wa",
+ "53104329bd718db46d8f021c13f1e2b0e726",
{
"chain": "test",
"isPrivkey": false,
@@ -208,8 +208,8 @@
}
],
[
- "tb1q0sqzfp3zj42u0perxr6jahhu4y03uw4dypk6sc",
- "00147c002486229555c7872330f52edefca91f1e3aad",
+ "tb1q3vya2h5435jkugq2few7dmktlrwq4ejmfaw7kr",
+ "00148b09d55e958d256e200a4e5de6eecbf8dc0ae65b",
{
"chain": "signet",
"isPrivkey": false,
@@ -217,8 +217,8 @@
}
],
[
- "tb1q9jv4qnawnuevqaeadn47gkq05ev78m4qg3zqejykdr9u0cm7yutq6gu5dj",
- "00202c99504fae9f32c0773d6cebe4580fa659e3eea044440cc89668cbc7e37e2716",
+ "tb1qxkhrl2s6ttrclckldruea0e8anhrehffl8xv7t0pdyrzm08v2hyqy408nf",
+ "002035ae3faa1a5ac78fe2df68f99ebf27ecee3cdd29f9cccf2de169062dbcec55c8",
{
"chain": "signet",
"isPrivkey": false,
@@ -226,8 +226,8 @@
}
],
[
- "tb1pxqf7d825wjtcftj7uep8w24jq3tz8vudfaqj20rns8ahqya56gcs92eqtu",
- "51203013e69d54749784ae5ee642772ab2045623b38d4f41253c7381fb7013b4d231",
+ "tb1pae5um27ahn8n73pgexe3kcwlp8dhswpn684h2k2w6t9a7w3eq65qephd5y",
+ "5120ee69cdabddbccf3f4428c9b31b61df09db783833d1eb75594ed2cbdf3a3906a8",
{
"chain": "signet",
"isPrivkey": false,
@@ -235,8 +235,8 @@
}
],
[
- "tb1rsrzkyvu2rt0dcgexajtazlw5nft4j7494ay396q6auw9375wxsrsgag884",
- "532080c562338a1adedc2326ec97d17dd49a57597aa5af4912e81aef1c58fa8e3407",
+ "tb1rx9n9g37az8mu236e5jpxdt0m67y4fuq8rhs0ss3djnm0kscfrwvq0ntlyg",
+ "532031665447dd11f7c54759a48266adfbd78954f0071de0f8422d94f6fb43091b98",
{
"chain": "signet",
"isPrivkey": false,
@@ -244,8 +244,8 @@
}
],
[
- "bcrt1qwf52dt9y2sv0f7fwkcpmtfjf74d4np2saeljt6",
- "00147268a6aca45418f4f92eb603b5a649f55b598550",
+ "bcrt1qdavt4j2sd7dlhqsavtnfxvzppw6k7qy97tmnu9",
+ "00146f58bac9506f9bfb821d62e69330410bb56f0085",
{
"chain": "regtest",
"isPrivkey": false,
@@ -253,8 +253,8 @@
}
],
[
- "bcrt1q0lma84unycxl4n96etffthqlf7y5axyp4fxf64kmhymvw8l6pwfs39futd",
- "00207ff7d3d793260dfaccbacad295dc1f4f894e9881aa4c9d56dbb936c71ffa0b93",
+ "bcrt1qan8gntac7z7me2ejt4hpru42ad2f759fmy0m3ejvs98656znv7eqga4uhv",
+ "0020ecce89afb8f0bdbcab325d6e11f2aaeb549f50a9d91fb8e64c814faa685367b2",
{
"chain": "regtest",
"isPrivkey": false,
@@ -262,8 +262,8 @@
}
],
[
- "bcrt1p3xat2ryucc2v0adrktqnavfzttvezrr27ngltsa2726p2ehvxz4se722v2",
- "512089bab50c9cc614c7f5a3b2c13eb1225ad9910c6af4d1f5c3aaf2b41566ec30ab",
+ "bcrt1pfwxjqvtt4tcxrtdluukfmy2dv7xd2qzdfy6kajv5nwn4yam3wxkq3553uh",
+ "51204b8d20316baaf061adbfe72c9d914d678cd5004d49356ec9949ba752777171ac",
{
"chain": "regtest",
"isPrivkey": false,
@@ -271,8 +271,8 @@
}
],
[
- "bcrt1saflydw6e26xhp29euhy5jke5jjqyywk3wvtc9ulgw9dvxyuqy9hdnxthyw755c7ldavy7u",
- "6028ea7e46bb59568d70a8b9e5c9495b349480423ad1731782f3e8715ac31380216ed9997723bd4a63df",
+ "bcrt1sx6p8njlx7h9mc2agz4yg82dzne23050ncq72cneeecez2pst8mahn8xecsf8g6hzx94420",
+ "6028368279cbe6f5cbbc2ba8154883a9a29e5517d1f3c03cac4f39ce3225060b3efb799cd9c412746ae2",
{
"chain": "regtest",
"isPrivkey": false,
@@ -280,72 +280,72 @@
}
],
[
- "16y3Q1XVRZqMR9T1XL1FkvNtD2E1bXBuYa",
- "76a9144171ec673aeb9fcf42af6094a3c82207e3b9a78188ac",
+ "1FjL87pn8ky6Vbavd1ZHeChRXtoxwRGCRd",
+ "76a914a19331b7b2627e663e25a7b001e4c0dcc5e21bc788ac",
{
"chain": "main",
"isPrivkey": false
}
],
[
- "3CmZZnAiHVQgiAKSakf864oJMxN2BP1eLC",
- "a914798575fc1041b9440c4e63c28e57e597d00b7e4387",
+ "3BZECeAH8gSKkjrTx8PwMrNQBLG18yHpvf",
+ "a9146c382dcdf5b284760c8e3fead91f7422cd76aa8787",
{
"chain": "main",
"isPrivkey": false
}
],
[
- "mtCB3SoBo7EYUv8j54kUubGY4x3aJPY8nk",
- "76a9148b0c5f9ee714e0d1d24642ad63d9d5f398d9b56588ac",
+ "n4YNbYuFdPwFrxSP8sjHFbAhUbLMUiY9jE",
+ "76a914fc8f9851f3c1e4719cd0b8e4816dd4e88c72e52888ac",
{
"chain": "test",
"isPrivkey": false
}
],
[
- "2N5ymzzKpx6EdUR4UdMZ7t9hcuwqtpHwgw5",
- "a9148badb3c3b5c0d39f906f7618e0018b7eae4baf7387",
+ "2NAeQVZayzVFAtgeC3iYJsjpjWDmsDph71A",
+ "a914bedc797342c03fd7a346c4c7857ca03d467013b687",
{
"chain": "test",
"isPrivkey": false
}
],
[
- "myXnpYbub28zgiJupDdZSWZtDbjcyfJVby",
- "76a914c59ac57661b57daadd7c0caf7318c14f54c6c0fa88ac",
+ "mnCBpkNMJEJLehgdEkzSo2eioniyJMxLpZ",
+ "76a914493c455551e48a1423263b62b127b436106a685488ac",
{
"chain": "signet",
"isPrivkey": false
}
],
[
- "2MtLg8jS5jSXm9evMzTtvpLjy26dBmjFEoT",
- "a9140c0007e89cea625d3bf9543baa5a470bb7e5b67287",
+ "2N5sNHomeNJDZv67AcFx9ES7FBZY4jx9KDA",
+ "a9148a776a0f34d56b63e7c595f2b205dbe1c393617a87",
{
"chain": "signet",
"isPrivkey": false
}
],
[
- "mzCyqdf2UNGdpgkD9NBgLcxdwXRg1i9buY",
- "76a914cd04311bdd1ef9c5c24e41930e032aade82a863a88ac",
+ "mfhE6jAUwjUDNZhaX1PAsDTKfneQF2Nshc",
+ "76a91401f15a4cc063dae4f4d56b89bfbc8bcc9ae5387c88ac",
{
"chain": "regtest",
"isPrivkey": false
}
],
[
- "2N3zGiwFku2vQjYnAqXv5Qu2ztfYRhh7tbF",
- "a91475d56d75c88e704d6c72fbe84ac1505abf736b4087",
+ "2MxNm1VHyVU4RuP3u1c1v5aQLk2dQjwy1Qk",
+ "a91438456f7c076356abadcc67b92ad777eb20fb9f8887",
{
"chain": "regtest",
"isPrivkey": false
}
],
[
- "5JUHCgyxNSHg64wwju72eNsG6ajqo4Z2fHHw9iLDLfh69rSiL7w",
- "5644d06d88855dacf3192a31df8f4acd8e4c155c52a86d2c1fa48303f5cff053",
+ "5HsL2nZuEebU5nM3RxNVQD9GcAnvNMahqQskf4fkqHe54zwd14e",
+ "06e8649790a90615a46d22dd762e0c42615336745356c2e16147c0f3d46b40d5",
{
"chain": "main",
"isCompressed": false,
@@ -353,8 +353,8 @@
}
],
[
- "L2kZaexG69VSriMe9T2m1jkS86iPe3xNbjcdfakRC1PHe7ay78Ji",
- "a50ee94aefcabf5a5d7c85be5b3844dee03c5604861dbfc77fe388c91e5a30f8",
+ "KwuVvu6hsuEMHrfFWJQV64tRrWX3QzqHH18JuAHYqYV6dqBvNKxd",
+ "147804bf8a0dfff35939a611c7f5a60ac107f33f33d6059f273d2079ab1d90f2",
{
"chain": "main",
"isCompressed": true,
@@ -362,8 +362,8 @@
}
],
[
- "927JwT1ViCr5TD2ZX8CsMNhg17dXmou5xu4y2KiH54zD7i34UJq",
- "4502a54c0026b0150281d41f40860d1e23870c63cdc32645bbed688f2ee41f64",
+ "921M1RNxghFcsVGqAJksQVbSgx36Yz4u6vebfz1wDujNvgNt93B",
+ "3777b341c45e2a9b9bf6bfb71dc7d129f64f1b9406ed4f93ade8f56065f1b732",
{
"chain": "test",
"isCompressed": false,
@@ -371,8 +371,8 @@
}
],
[
- "cTpGGNPVy2Eagawohbr4aGtRJzpLnjxGsGYh9DUcBM45f3KdKGF6",
- "ba005a0cb39587aab00bd54c848b59e8adaed47403228567ddc739c2a344ff59",
+ "cNEnbfF2fcxmmCLWqMAaq6fxJvVkwMbyU3kCbpQznz4Z1j6TZDGb",
+ "1397b0d4a03e1ab2c54dd9af99ce1ecbfb90c80a58886da95e1181a55703d96b",
{
"chain": "test",
"isCompressed": true,
@@ -380,8 +380,8 @@
}
],
[
- "932PLCLA19yPNqV67qwHBSGjxi82LVzWBF7josL9ab4Q1kxgPGF",
- "bd8677e076eb39770bf7e9f9e8d3f2cf257effab9b4c220fd3439ccfc208c984",
+ "93BcpCMKPmFCuY8bqS4k3HFrhJ1Afxi4uSsEeJFvX86GYW7PC7W",
+ "d27d1b6ef55ca2e4d475b5276f2dbb85f7a6459dceeb89c67b776fd3bb974452",
{
"chain": "signet",
"isCompressed": false,
@@ -389,8 +389,8 @@
}
],
[
- "cViUpEy8URSsLjUvxwL7cEuNgCVqM7oKBzd1ZPbA4khcQsQJuj1j",
- "f2b36ade8393e29dc71e52cb75ba1109ba210203cd7d0a5ae881ad6846516203",
+ "cUtwbyxoL1owPxUafgH2meEpydeywjhnTYv2mJaFHHchz39AaEgy",
+ "da3ed4ef1647e1733ec076919cab6156077ed9532e7c365acc425747e198b3e1",
{
"chain": "signet",
"isCompressed": true,
@@ -398,8 +398,8 @@
}
],
[
- "92jddDjJCVDmJtgvBHQ9i58PMash8kwsYhRdNo22ea2MYPXdCBE",
- "977bf8686f1bcad28f86c4c14afbd33215746bd19203647bf7ff9c6fddc9cc87",
+ "927zPWny2SiNaUmHF5NnGQXQWDwbByfFzXGgu88j91ZoutSosvE",
+ "468e0284f230153db8687d8ec23db079a5b67d72ca04174b3867b13e4ea9945e",
{
"chain": "regtest",
"isCompressed": false,
@@ -407,8 +407,8 @@
}
],
[
- "cVwAuMoUqRo399X7vXzuzQyPEvZJMXM8c82zHzRkFCxPCSGx8A6y",
- "f93acbbce02b8cb9ddca3fad495441e324cc01eb640b0a7b4c9f0e31644c822a",
+ "cRez45VGSp5EXNqm89K3NJJPSKKapJg5Kbw3atxr2337x2gtgYed",
+ "798d87586cffbe8c545ab374454e403b1eb831501ebe89f3c3b02f3137bd7b46",
{
"chain": "regtest",
"isCompressed": true,
@@ -416,8 +416,8 @@
}
],
[
- "bc1qz377zwe5awr68dnggengqx9vrjt05k98q3sw2n",
- "0014147de13b34eb87a3b66846668018ac1c96fa58a7",
+ "bc1qhxt04s5xnpy0kxw4x99n5hpdf5pmtzpqs52es2",
+ "0014b996fac2869848fb19d5314b3a5c2d4d03b58820",
{
"chain": "main",
"isPrivkey": false,
@@ -425,8 +425,8 @@
}
],
[
- "bc1qkmhskpdzg8kdkfywhu09kswwn9qan9vnkrf6mk40jvnr06s6sz5ssf82ya",
- "0020b6ef0b05a241ecdb248ebf1e5b41ce9941d99593b0d3addaaf932637ea1a80a9",
+ "bc1qgc9ljrvdf2e0zg9rmmq86xklqwfys7r6wptjlacdgrcdc7sa6ggqu4rrxf",
+ "0020460bf90d8d4ab2f120a3dec07d1adf039248787a70572ff70d40f0dc7a1dd210",
{
"chain": "main",
"isPrivkey": false,
@@ -434,8 +434,8 @@
}
],
[
- "bc1ps8cndas60cntk8x79sg9f5e5jz7x050z8agyugln2ukkks23rryqpejzkc",
- "512081f136f61a7e26bb1cde2c1054d33490bc67d1e23f504e23f3572d6b415118c8",
+ "bc1pve739yap4uxjvfk0jrey69078u0gasm2nwvv483ec6zkzulgw9xqu4w9fd",
+ "5120667d1293a1af0d2626cf90f24d15fe3f1e8ec36a9b98ca9e39c6856173e8714c",
{
"chain": "main",
"isPrivkey": false,
@@ -443,8 +443,8 @@
}
],
[
- "bc1zn4tsczge9l",
- "52029d57",
+ "bc1zmjtqxkzs89",
+ "5202dc96",
{
"chain": "main",
"isPrivkey": false,
@@ -452,8 +452,8 @@
}
],
[
- "tb1q6xw0wwd9n9d7ge87dryz4vm5vtahzhvz6yett3",
- "0014d19cf739a5995be464fe68c82ab37462fb715d82",
+ "tb1ql4k5ayv7p7w0t0ge7tpntgpkgw53g2payxkszr",
+ "0014fd6d4e919e0f9cf5bd19f2c335a03643a914283d",
{
"chain": "test",
"isPrivkey": false,
@@ -461,8 +461,8 @@
}
],
[
- "tb1qwn9zq9fu5uk35ykpgsc7rz4uawy4yh0r5m5er26768h5ur50su3qj6evun",
- "002074ca20153ca72d1a12c14431e18abceb89525de3a6e991ab5ed1ef4e0e8f8722",
+ "tb1q9jx3x2qqdpempxrcfgyrkjd5fzeacaqj4ua7cs7fe2sfd2wdaueq5wn26y",
+ "00202c8d1328006873b098784a083b49b448b3dc7412af3bec43c9caa096a9cdef32",
{
"chain": "test",
"isPrivkey": false,
@@ -470,8 +470,8 @@
}
],
[
- "tb1pmcdc5d8gr92rtemfsnhpeqanvs0nr82upn5dktxluz9n0qcv34lqxke0wq",
- "5120de1b8a34e8195435e76984ee1c83b3641f319d5c0ce8db2cdfe08b37830c8d7e",
+ "tb1pdswckwd9ym5yf5eyzg8j4jjwnzla8y0tf9cp7aasfkek0u29sz9qfr00yf",
+ "51206c1d8b39a526e844d324120f2aca4e98bfd391eb49701f77b04db367f145808a",
{
"chain": "test",
"isPrivkey": false,
@@ -479,8 +479,8 @@
}
],
[
- "tb1rgxjvtfzp0xczz6dlzqv8d5cmuykk4qkk",
- "531041a4c5a44179b02169bf101876d31be1",
+ "tb1r0ecpfxg2udhtc556gqrpwwhk4sw3f0kc",
+ "53107e7014990ae36ebc529a4006173af6ac",
{
"chain": "test",
"isPrivkey": false,
@@ -488,8 +488,8 @@
}
],
[
- "tb1qa9dlyt6fydestul4y4wh72yshh044w32np8etk",
- "0014e95bf22f49237305f3f5255d7f2890bddf5aba2a",
+ "tb1q6mwf89hnqhlu8txjgjfs4s7p93ugffn3k062ll",
+ "0014d6dc9396f305ffc3acd244930ac3c12c7884a671",
{
"chain": "signet",
"isPrivkey": false,
@@ -497,8 +497,8 @@
}
],
[
- "tb1qu4p26n0033720xm0rjgkds5ehdwf039k2fgv75um5krrvfhrrj7qckl9r2",
- "0020e542ad4def8c7ca79b6f1c9166c299bb5c97c4b65250cf539ba5863626e31cbc",
+ "tb1qafrjalu4d73dql0czau9j6z422434kef235mzljf48ckd5xz3sys09jm97",
+ "0020ea472eff956fa2d07df8177859685552ab1adb295469b17e49a9f166d0c28c09",
{
"chain": "signet",
"isPrivkey": false,
@@ -506,8 +506,8 @@
}
],
[
- "tb1pjyukm4n4flwd0ey3lrl06c9kalr60ggmlkcxq2rhhxmy4lvkmkpqexdzqy",
- "512091396dd6754fdcd7e491f8fefd60b6efc7a7a11bfdb0602877b9b64afd96dd82",
+ "tb1pwst9qszjrhuv2e7as0flcq9gm698v6gdxzz9e87p07s8rssdx3zqklm3vf",
+ "512074165040521df8c567dd83d3fc00a8de8a76690d30845c9fc17fa071c20d3444",
{
"chain": "signet",
"isPrivkey": false,
@@ -515,8 +515,8 @@
}
],
[
- "tb1r4k75s5syvewsvxufdc3xfhf4tw4u30alw39xny3dnxrl6hau7systymfdv",
- "5320adbd485204665d061b896e2264dd355babc8bfbf744a69922d9987fd5fbcf409",
+ "tb1r3ss76jtsuxe8c8c8lxsehnpak55ylrgr345pww076l536ahjr6jsydamx3",
+ "53208c21ed4970e1b27c1f07f9a19bcc3db5284f8d038d681739fed7e91d76f21ea5",
{
"chain": "signet",
"isPrivkey": false,
@@ -524,8 +524,8 @@
}
],
[
- "bcrt1qnk3tdwwj47ppc4pqmxkjdusegedn9ru5gvccwa",
- "00149da2b6b9d2af821c5420d9ad26f219465b328f94",
+ "bcrt1q65nhlm4hf2ptg3t264al57p7wjxj2c3s6kyt83",
+ "0014d5277feeb74a82b4456ad57bfa783e748d256230",
{
"chain": "regtest",
"isPrivkey": false,
@@ -533,8 +533,8 @@
}
],
[
- "bcrt1qz7prfshfkwsxuk72pt6mzr6uumq4qllxe4vmwqt89tat48d362yqlykk6a",
- "0020178234c2e9b3a06e5bca0af5b10f5ce6c1507fe6cd59b701672afaba9db1d288",
+ "bcrt1qawvc90lpytw3z3k9etdx54l0exq5f5sqfzu5e45kjnl6slwayeeqx2dyac",
+ "0020eb9982bfe122dd1146c5cada6a57efc98144d20048b94cd69694ffa87ddd2672",
{
"chain": "regtest",
"isPrivkey": false,
@@ -542,8 +542,8 @@
}
],
[
- "bcrt1pumee3wj80xvyr7wjmj7zsk26x5pn095aegy862yhx6f2j9sgc9hq6cj4cm",
- "5120e6f398ba47799841f9d2dcbc28595a350337969dca087d28973692a91608c16e",
+ "bcrt1p39a4s4vdcw9kqa8w2t0rp7aj8kfxyw7mce5sk5d70x6wnnmpvt7skf2kxy",
+ "5120897b58558dc38b6074ee52de30fbb23d92623bdbc6690b51be79b4e9cf6162fd",
{
"chain": "regtest",
"isPrivkey": false,
@@ -551,8 +551,8 @@
}
],
[
- "bcrt1szqz8hj64d2hhc6nt65v09jxal66pgff2xpcp9kj648qkk8kjzxelsts4dktd799g47uase",
- "602810047bcb556aaf7c6a6bd518f2c8ddfeb414252a307012da5aa9c16b1ed211b3f82e156d96df14a8",
+ "bcrt1s489d9fhmyel0vzfqsrmew4x7r80asuqesm5hgqacy35daflcyufh3j8cgdtflvt99ph05m",
+ "6028a9cad2a6fb267ef6092080f79754de19dfd8701986e97403b82468dea7f8271378c8f843569fb165",
{
"chain": "regtest",
"isPrivkey": false,
@@ -560,48 +560,48 @@
}
],
[
- "12agZTajtRE3STSchwWNWnrm467zzTQ916",
- "76a9141156e00f70061e5faba8b71593a8c7554b47090c88ac",
+ "1G9A9j6W8TLuh6dEeVwWeyibK1Uc5MfVFV",
+ "76a914a614da54daacdb8861f451a0b7e3c27cdf8a099e88ac",
{
"chain": "main",
"isPrivkey": false
}
],
[
- "3NXqB6iZiPYbKruNT3d9xNBTmtb73xMvvf",
- "a914e49decc9e5d97e0547d3642f3a4795b13ae62bca87",
+ "33GA3ZXbw5o5HeUrBEaqkWXFYYZmdxGRRP",
+ "a914113ca1afeb49ff3abf176ffa19c2a2b4df19712a87",
{
"chain": "main",
"isPrivkey": false
}
],
[
- "mjgt4BoCYxjzWvJFoh68x7cj5GeaKDYhyx",
- "76a9142dc11fc7b8072f733f690ffb0591c00f4062295c88ac",
+ "mwgS2HRbjyfYxFnR1nF9VKLvmdgMfFBmGq",
+ "76a914b14ce7070b53cb0e4b5b5f6e253e876990aeca2e88ac",
{
"chain": "test",
"isPrivkey": false
}
],
[
- "2NCT6FdQ5MxorHgnFxLeHyGwTGRdkHcrJDH",
- "a914d2a8ec992b0894a0d9391ca5d9c45c388c41be7e87",
+ "2MwBVrJQ76BdaGD76CTmou8cZzQYLpe4NqU",
+ "a9142b2c149cde619eae3d7fe995243b76a3417541aa87",
{
"chain": "test",
"isPrivkey": false
}
],
[
- "mpomiA7wqDnMcxaNLC23eBuXAb4U6H4ZqW",
- "76a91465e75e340415ed297c58d6a14d3c17ceeaa17bbd88ac",
+ "mfnJ8tEkqKNFE5YaHTXFxyHk2mnDK2fvDh",
+ "76a91402e6cd77e649ad8b281271f158fc964ca3f66cb088ac",
{
"chain": "signet",
"isPrivkey": false
}
],
[
- "2N1pGAA5uatbU2PKvMA9BnJmHcK6yHfMiZa",
- "a9145e008b6cc232164570befc23d216060bf4ea793b87",
+ "2My83D67ir7K8PPzeT6mE2oth3ZwNTVRS9F",
+ "a9144074d84d32ff62da7b1b3c61925b934bfeb34b0587",
{
"chain": "signet",
"isPrivkey": false
diff --git a/src/test/util/logging.h b/src/test/util/logging.h
index ebe0ecf623..f477088392 100644
--- a/src/test/util/logging.h
+++ b/src/test/util/logging.h
@@ -36,6 +36,6 @@ public:
~DebugLogHelper() { check_found(); }
};
-#define ASSERT_DEBUG_LOG(message) DebugLogHelper PASTE2(debugloghelper, __COUNTER__)(message)
+#define ASSERT_DEBUG_LOG(message) DebugLogHelper UNIQUE_NAME(debugloghelper)(message)
#endif // BITCOIN_TEST_UTIL_LOGGING_H
diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp
index 211153f06c..13f17ca277 100644
--- a/src/test/util/setup_common.cpp
+++ b/src/test/util/setup_common.cpp
@@ -15,10 +15,10 @@
#include <interfaces/chain.h>
#include <net.h>
#include <net_processing.h>
-#include <node/miner.h>
-#include <noui.h>
#include <node/blockstorage.h>
#include <node/chainstate.h>
+#include <node/miner.h>
+#include <noui.h>
#include <policy/fees.h>
#include <pow.h>
#include <rpc/blockchain.h>
@@ -28,6 +28,7 @@
#include <script/sigcache.h>
#include <shutdown.h>
#include <streams.h>
+#include <test/util/net.h>
#include <txdb.h>
#include <util/strencodings.h>
#include <util/string.h>
@@ -226,7 +227,7 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector<const
/*deterministic=*/false,
m_node.args->GetIntArg("-checkaddrman", 0));
m_node.banman = std::make_unique<BanMan>(m_args.GetDataDirBase() / "banlist", nullptr, DEFAULT_MISBEHAVING_BANTIME);
- m_node.connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman); // Deterministic randomness for tests.
+ m_node.connman = std::make_unique<ConnmanTestMsg>(0x1337, 0x1337, *m_node.addrman); // Deterministic randomness for tests.
m_node.peerman = PeerManager::make(chainparams, *m_node.connman, *m_node.addrman,
m_node.banman.get(), *m_node.chainman,
*m_node.mempool, false);
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index f73cc5da5f..65c8b4ea60 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -481,8 +481,6 @@ void CTxMemPool::addUnchecked(const CTxMemPoolEntry &entry, setEntries &setAnces
indexed_transaction_set::iterator newit = mapTx.insert(entry).first;
// Update transaction for any feeDelta created by PrioritiseTransaction
- // TODO: refactor so that the fee delta is calculated before inserting
- // into mapTx.
CAmount delta{0};
ApplyDelta(entry.GetTx().GetHash(), delta);
if (delta) {
diff --git a/src/util/epochguard.h b/src/util/epochguard.h
index 0fec7d2624..7f6477fb3b 100644
--- a/src/util/epochguard.h
+++ b/src/util/epochguard.h
@@ -7,6 +7,7 @@
#define BITCOIN_UTIL_EPOCHGUARD_H
#include <threadsafety.h>
+#include <util/macros.h>
#include <cassert>
@@ -96,6 +97,6 @@ public:
}
};
-#define WITH_FRESH_EPOCH(epoch) const Epoch::Guard PASTE2(epoch_guard_, __COUNTER__)(epoch)
+#define WITH_FRESH_EPOCH(epoch) const Epoch::Guard UNIQUE_NAME(epoch_guard_)(epoch)
#endif // BITCOIN_UTIL_EPOCHGUARD_H
diff --git a/src/util/macros.h b/src/util/macros.h
index c9740c8e82..bf6ba665dc 100644
--- a/src/util/macros.h
+++ b/src/util/macros.h
@@ -8,6 +8,8 @@
#define PASTE(x, y) x ## y
#define PASTE2(x, y) PASTE(x, y)
+#define UNIQUE_NAME(name) PASTE2(name, __COUNTER__)
+
/**
* Converts the parameter X to a string after macro replacement on X has been performed.
* Don't merge these into one macro!
diff --git a/src/wallet/rpc/wallet.cpp b/src/wallet/rpc/wallet.cpp
index 4baf16fdcb..1291663847 100644
--- a/src/wallet/rpc/wallet.cpp
+++ b/src/wallet/rpc/wallet.cpp
@@ -257,7 +257,7 @@ static RPCHelpMan setwalletflag()
{
{RPCResult::Type::STR, "flag_name", "The name of the flag that was modified"},
{RPCResult::Type::BOOL, "flag_state", "The new state of the flag"},
- {RPCResult::Type::STR, "warnings", "Any warnings associated with the change"},
+ {RPCResult::Type::STR, "warnings", /*optional=*/true, "Any warnings associated with the change"},
}
},
RPCExamples{
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 2a0653c719..c3ae098aee 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -299,6 +299,13 @@ std::shared_ptr<CWallet> CreateWallet(WalletContext& context, const std::string&
return nullptr;
}
+ // Do not allow a passphrase when private keys are disabled
+ if (!passphrase.empty() && (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
+ error = Untranslated("Passphrase provided but private keys are disabled. A passphrase is only used to encrypt private keys, so cannot be used for wallets with private keys disabled.");
+ status = DatabaseStatus::FAILED_CREATE;
+ return nullptr;
+ }
+
// Wallet::Verify will check if we're trying to create a wallet with a duplicate name.
std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(name, options, status, error);
if (!database) {
@@ -307,13 +314,6 @@ std::shared_ptr<CWallet> CreateWallet(WalletContext& context, const std::string&
return nullptr;
}
- // Do not allow a passphrase when private keys are disabled
- if (!passphrase.empty() && (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
- error = Untranslated("Passphrase provided but private keys are disabled. A passphrase is only used to encrypt private keys, so cannot be used for wallets with private keys disabled.");
- status = DatabaseStatus::FAILED_CREATE;
- return nullptr;
- }
-
// Make the wallet
context.chain->initMessage(_("Loading wallet…").translated);
const std::shared_ptr<CWallet> wallet = CWallet::Create(context, name, std::move(database), wallet_creation_flags, error, warnings);
diff --git a/test/README.md b/test/README.md
index 7ff2d6d9f2..e5a184d23c 100644
--- a/test/README.md
+++ b/test/README.md
@@ -305,9 +305,9 @@ Use the `-v` option for verbose output.
| Lint test | Dependency |
|-----------|:----------:|
-| [`lint-python.sh`](lint/lint-python.sh) | [flake8](https://gitlab.com/pycqa/flake8)
-| [`lint-python.sh`](lint/lint-python.sh) | [mypy](https://github.com/python/mypy)
-| [`lint-python.sh`](lint/lint-python.sh) | [pyzmq](https://github.com/zeromq/pyzmq)
+| [`lint-python.py`](lint/lint-python.py) | [flake8](https://gitlab.com/pycqa/flake8)
+| [`lint-python.py`](lint/lint-python.py) | [mypy](https://github.com/python/mypy)
+| [`lint-python.py`](lint/lint-python.py) | [pyzmq](https://github.com/zeromq/pyzmq)
| [`lint-python-dead-code.py`](lint/lint-python-dead-code.py) | [vulture](https://github.com/jendrikseipp/vulture)
| [`lint-shell.sh`](lint/lint-shell.sh) | [ShellCheck](https://github.com/koalaman/shellcheck)
| [`lint-spelling.py`](lint/lint-spelling.py) | [codespell](https://github.com/codespell-project/codespell)
diff --git a/test/config.ini.in b/test/config.ini.in
index d7105c419b..5888ef443b 100644
--- a/test/config.ini.in
+++ b/test/config.ini.in
@@ -19,6 +19,7 @@ RPCAUTH=@abs_top_srcdir@/share/rpcauth/rpcauth.py
@USE_SQLITE_TRUE@USE_SQLITE=true
@USE_BDB_TRUE@USE_BDB=true
@BUILD_BITCOIN_CLI_TRUE@ENABLE_CLI=true
+@BUILD_BITCOIN_UTIL_TRUE@ENABLE_BITCOIN_UTIL=true
@BUILD_BITCOIN_WALLET_TRUE@ENABLE_WALLET_TOOL=true
@BUILD_BITCOIND_TRUE@ENABLE_BITCOIND=true
@ENABLE_FUZZ_TRUE@ENABLE_FUZZ=true
diff --git a/test/functional/README.md b/test/functional/README.md
index 926810cf03..914dbfd977 100644
--- a/test/functional/README.md
+++ b/test/functional/README.md
@@ -24,7 +24,7 @@ don't have test cases for.
Consider using [pyenv](https://github.com/pyenv/pyenv), which checks [.python-version](/.python-version),
to prevent accidentally introducing modern syntax from an unsupported Python version.
The CI linter job also checks this, but [possibly not in all cases](https://github.com/bitcoin/bitcoin/pull/14884#discussion_r239585126).
-- See [the python lint script](/test/lint/lint-python.sh) that checks for violations that
+- See [the python lint script](/test/lint/lint-python.py) that checks for violations that
could lead to bugs and issues in the test code.
- Use [type hints](https://docs.python.org/3/library/typing.html) in your code to improve code readability
and to detect possible bugs earlier.
diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py
index 2fb9ec0942..a39ee003ef 100755
--- a/test/functional/test_framework/test_framework.py
+++ b/test/functional/test_framework/test_framework.py
@@ -244,8 +244,14 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
"src",
"bitcoin-cli" + config["environment"]["EXEEXT"],
)
+ fname_bitcoinutil = os.path.join(
+ config["environment"]["BUILDDIR"],
+ "src",
+ "bitcoin-util" + config["environment"]["EXEEXT"],
+ )
self.options.bitcoind = os.getenv("BITCOIND", default=fname_bitcoind)
self.options.bitcoincli = os.getenv("BITCOINCLI", default=fname_bitcoincli)
+ self.options.bitcoinutil = os.getenv("BITCOINUTIL", default=fname_bitcoinutil)
os.environ['PATH'] = os.pathsep.join([
os.path.join(config['environment']['BUILDDIR'], 'src'),
@@ -880,6 +886,11 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
if not self.is_wallet_tool_compiled():
raise SkipTest("bitcoin-wallet has not been compiled")
+ def skip_if_no_bitcoin_util(self):
+ """Skip the running test if bitcoin-util has not been compiled."""
+ if not self.is_bitcoin_util_compiled():
+ raise SkipTest("bitcoin-util has not been compiled")
+
def skip_if_no_cli(self):
"""Skip the running test if bitcoin-cli has not been compiled."""
if not self.is_cli_compiled():
@@ -927,6 +938,10 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
"""Checks whether bitcoin-wallet was compiled."""
return self.config["components"].getboolean("ENABLE_WALLET_TOOL")
+ def is_bitcoin_util_compiled(self):
+ """Checks whether bitcoin-util was compiled."""
+ return self.config["components"].getboolean("ENABLE_BITCOIN_UTIL")
+
def is_zmq_compiled(self):
"""Checks whether the zmq module was compiled."""
return self.config["components"].getboolean("ENABLE_ZMQ")
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index 1f0f806d91..a3c938ae26 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -145,6 +145,8 @@ BASE_SCRIPTS = [
'wallet_txn_doublespend.py --mineblock',
'tool_wallet.py --legacy-wallet',
'tool_wallet.py --descriptors',
+ 'tool_signet_miner.py --legacy-wallet',
+ 'tool_signet_miner.py --descriptors',
'wallet_txn_clone.py',
'wallet_txn_clone.py --segwit',
'rpc_getchaintips.py',
diff --git a/test/functional/tool_signet_miner.py b/test/functional/tool_signet_miner.py
new file mode 100755
index 0000000000..e6fc9072ab
--- /dev/null
+++ b/test/functional/tool_signet_miner.py
@@ -0,0 +1,62 @@
+#!/usr/bin/env python3
+# Copyright (c) 2022 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Test signet miner tool"""
+
+import os.path
+import subprocess
+import sys
+import time
+
+from test_framework.key import ECKey
+from test_framework.script_util import key_to_p2wpkh_script
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import assert_equal
+from test_framework.wallet_util import bytes_to_wif
+
+
+CHALLENGE_PRIVATE_KEY = (42).to_bytes(32, 'big')
+
+
+class SignetMinerTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.chain = "signet"
+ self.setup_clean_chain = True
+ self.num_nodes = 1
+
+ # generate and specify signet challenge (simple p2wpkh script)
+ privkey = ECKey()
+ privkey.set(CHALLENGE_PRIVATE_KEY, True)
+ pubkey = privkey.get_pubkey().get_bytes()
+ challenge = key_to_p2wpkh_script(pubkey)
+ self.extra_args = [[f'-signetchallenge={challenge.hex()}']]
+
+ def skip_test_if_missing_module(self):
+ self.skip_if_no_cli()
+ self.skip_if_no_wallet()
+ self.skip_if_no_bitcoin_util()
+
+ def run_test(self):
+ node = self.nodes[0]
+ # import private key needed for signing block
+ node.importprivkey(bytes_to_wif(CHALLENGE_PRIVATE_KEY))
+
+ # generate block with signet miner tool
+ base_dir = self.config["environment"]["SRCDIR"]
+ signet_miner_path = os.path.join(base_dir, "contrib", "signet", "miner")
+ subprocess.run([
+ sys.executable,
+ signet_miner_path,
+ f'--cli={node.cli.binary} -datadir={node.cli.datadir}',
+ 'generate',
+ f'--address={node.getnewaddress()}',
+ f'--grind-cmd={self.options.bitcoinutil} grind',
+ '--nbits=1d00ffff',
+ f'--set-block-time={int(time.time())}',
+ ], check=True, stderr=subprocess.STDOUT)
+ assert_equal(node.getblockcount(), 1)
+
+
+if __name__ == "__main__":
+ SignetMinerTest().main()
diff --git a/test/functional/wallet_avoidreuse.py b/test/functional/wallet_avoidreuse.py
index dc823c2c60..f663666f57 100755
--- a/test/functional/wallet_avoidreuse.py
+++ b/test/functional/wallet_avoidreuse.py
@@ -118,6 +118,17 @@ class AvoidReuseTest(BitcoinTestFramework):
assert_raises_rpc_error(-8, "Wallet flag is already set to false", self.nodes[0].setwalletflag, 'avoid_reuse', False)
assert_raises_rpc_error(-8, "Wallet flag is already set to true", self.nodes[1].setwalletflag, 'avoid_reuse', True)
+ # Create a wallet with avoid reuse, and test that disabling it afterwards persists
+ self.nodes[1].createwallet(wallet_name="avoid_reuse_persist", avoid_reuse=True)
+ w = self.nodes[1].get_wallet_rpc("avoid_reuse_persist")
+ assert_equal(w.getwalletinfo()["avoid_reuse"], True)
+ w.setwalletflag("avoid_reuse", False)
+ assert_equal(w.getwalletinfo()["avoid_reuse"], False)
+ w.unloadwallet()
+ self.nodes[1].loadwallet("avoid_reuse_persist")
+ assert_equal(w.getwalletinfo()["avoid_reuse"], False)
+ w.unloadwallet()
+
def test_immutable(self):
'''Test immutable wallet flags'''
self.log.info("Test immutable wallet flags")
diff --git a/test/functional/wallet_createwallet.py b/test/functional/wallet_createwallet.py
index e8234de032..dcf2e98638 100755
--- a/test/functional/wallet_createwallet.py
+++ b/test/functional/wallet_createwallet.py
@@ -26,6 +26,11 @@ class CreateWalletTest(BitcoinTestFramework):
node = self.nodes[0]
self.generate(node, 1) # Leave IBD for sethdseed
+ self.log.info("Run createwallet with invalid parameters.")
+ # Run createwallet with invalid parameters. This must not prevent a new wallet with the same name from being created with the correct parameters.
+ assert_raises_rpc_error(-4, "Passphrase provided but private keys are disabled. A passphrase is only used to encrypt private keys, so cannot be used for wallets with private keys disabled.",
+ self.nodes[0].createwallet, wallet_name='w0', descriptors=True, disable_private_keys=True, passphrase="passphrase")
+
self.nodes[0].createwallet(wallet_name='w0')
w0 = node.get_wallet_rpc('w0')
address1 = w0.getnewaddress()
diff --git a/test/lint/lint-git-commit-check.py b/test/lint/lint-git-commit-check.py
new file mode 100755
index 0000000000..a1d03370e8
--- /dev/null
+++ b/test/lint/lint-git-commit-check.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2020-2022 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#
+# Linter to check that commit messages have a new line before the body
+# or no body at all
+
+import argparse
+import os
+import sys
+
+from subprocess import check_output
+
+
+def parse_args():
+ """Parse command line arguments."""
+ parser = argparse.ArgumentParser(
+ description="""
+ Linter to check that commit messages have a new line before
+ the body or no body at all.
+ """,
+ epilog=f"""
+ You can manually set the commit-range with the COMMIT_RANGE
+ environment variable (e.g. "COMMIT_RANGE='47ba2c3...ee50c9e'
+ {sys.argv[0]}"). Defaults to current merge base when neither
+ prev-commits nor the environment variable is set.
+ """)
+
+ parser.add_argument("--prev-commits", "-p", required=False, help="The previous n commits to check")
+
+ return parser.parse_args()
+
+
+def main():
+ args = parse_args()
+ exit_code = 0
+
+ if not os.getenv("COMMIT_RANGE"):
+ if args.prev_commits:
+ commit_range = "HEAD~" + args.prev_commits + "...HEAD"
+ else:
+ # This assumes that the target branch of the pull request will be master.
+ merge_base = check_output(["git", "merge-base", "HEAD", "master"], universal_newlines=True, encoding="utf8").rstrip("\n")
+ commit_range = merge_base + "..HEAD"
+ else:
+ commit_range = os.getenv("COMMIT_RANGE")
+
+ commit_hashes = check_output(["git", "log", commit_range, "--format=%H"], universal_newlines=True, encoding="utf8").splitlines()
+
+ for hash in commit_hashes:
+ commit_info = check_output(["git", "log", "--format=%B", "-n", "1", hash], universal_newlines=True, encoding="utf8").splitlines()
+ if len(commit_info) >= 2:
+ if commit_info[1]:
+ print(f"The subject line of commit hash {hash} is followed by a non-empty line. Subject lines should always be followed by a blank line.")
+ exit_code = 1
+
+ sys.exit(exit_code)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/test/lint/lint-git-commit-check.sh b/test/lint/lint-git-commit-check.sh
deleted file mode 100755
index f77373ed00..0000000000
--- a/test/lint/lint-git-commit-check.sh
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/usr/bin/env bash
-# Copyright (c) 2020-2021 The Bitcoin Core developers
-# Distributed under the MIT software license, see the accompanying
-# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#
-# Linter to check that commit messages have a new line before the body
-# or no body at all
-
-export LC_ALL=C
-
-EXIT_CODE=0
-
-while getopts "?" opt; do
- case $opt in
- ?)
- echo "Usage: $0 [N]"
- echo " COMMIT_RANGE='<commit range>' $0"
- echo " $0 -?"
- echo "Checks unmerged commits, the previous N commits, or a commit range."
- echo "COMMIT_RANGE='47ba2c3...ee50c9e' $0"
- exit ${EXIT_CODE}
- ;;
- esac
-done
-
-if [ -z "${COMMIT_RANGE}" ]; then
- if [ -n "$1" ]; then
- COMMIT_RANGE="HEAD~$1...HEAD"
- else
- # This assumes that the target branch of the pull request will be master.
- MERGE_BASE=$(git merge-base HEAD master)
- COMMIT_RANGE="$MERGE_BASE..HEAD"
- fi
-fi
-
-while IFS= read -r commit_hash || [[ -n "$commit_hash" ]]; do
- n_line=0
- while IFS= read -r line || [[ -n "$line" ]]; do
- n_line=$((n_line+1))
- length=${#line}
- if [ $n_line -eq 2 ] && [ "$length" -ne 0 ]; then
- echo "The subject line of commit hash ${commit_hash} is followed by a non-empty line. Subject lines should always be followed by a blank line."
- EXIT_CODE=1
- fi
- done < <(git log --format=%B -n 1 "$commit_hash")
-done < <(git log "${COMMIT_RANGE}" --format=%H)
-
-exit ${EXIT_CODE}
diff --git a/test/lint/lint-logs.py b/test/lint/lint-logs.py
new file mode 100755
index 0000000000..e6c4c068fb
--- /dev/null
+++ b/test/lint/lint-logs.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2018-2022 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#
+# Check that all logs are terminated with '\n'
+#
+# Some logs are continued over multiple lines. They should be explicitly
+# commented with /* Continued */
+
+import re
+import sys
+
+from subprocess import check_output
+
+
+def main():
+ logs_list = check_output(["git", "grep", "--extended-regexp", r"LogPrintf?\(", "--", "*.cpp"], universal_newlines=True, encoding="utf8").splitlines()
+
+ unterminated_logs = [line for line in logs_list if not re.search(r'(\\n"|/\* Continued \*/)', line)]
+
+ if unterminated_logs != []:
+ print("All calls to LogPrintf() and LogPrint() should be terminated with \\n")
+ print("")
+
+ for line in unterminated_logs:
+ print(line)
+
+ sys.exit(1)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/test/lint/lint-logs.sh b/test/lint/lint-logs.sh
deleted file mode 100755
index 6d5165f649..0000000000
--- a/test/lint/lint-logs.sh
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/env bash
-#
-# Copyright (c) 2018-2021 The Bitcoin Core developers
-# Distributed under the MIT software license, see the accompanying
-# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#
-# Check that all logs are terminated with '\n'
-#
-# Some logs are continued over multiple lines. They should be explicitly
-# commented with /* Continued */
-#
-# There are some instances of LogPrintf() in comments. Those can be
-# ignored
-
-export LC_ALL=C
-UNTERMINATED_LOGS=$(git grep --extended-regexp "LogPrintf?\(" -- "*.cpp" | \
- grep -v '\\n"' | \
- grep -v '\.\.\.' | \
- grep -v "/\* Continued \*/" | \
- grep -v "LogPrint()" | \
- grep -v "LogPrintf()")
-if [[ ${UNTERMINATED_LOGS} != "" ]]; then
- # shellcheck disable=SC2028
- echo "All calls to LogPrintf() and LogPrint() should be terminated with \\n"
- echo
- echo "${UNTERMINATED_LOGS}"
- exit 1
-fi
diff --git a/test/lint/lint-python.py b/test/lint/lint-python.py
new file mode 100755
index 0000000000..4d16facfea
--- /dev/null
+++ b/test/lint/lint-python.py
@@ -0,0 +1,131 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2022 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+"""
+Check for specified flake8 and mypy warnings in python files.
+"""
+
+import os
+import pkg_resources
+import subprocess
+import sys
+
+DEPS = ['flake8', 'mypy', 'pyzmq']
+MYPY_CACHE_DIR = f"{os.getenv('BASE_ROOT_DIR', '')}/test/.mypy_cache"
+FILES_ARGS = ['git', 'ls-files', 'test/functional/*.py', 'contrib/devtools/*.py']
+
+ENABLED = (
+ 'E101,' # indentation contains mixed spaces and tabs
+ 'E112,' # expected an indented block
+ 'E113,' # unexpected indentation
+ 'E115,' # expected an indented block (comment)
+ 'E116,' # unexpected indentation (comment)
+ 'E125,' # continuation line with same indent as next logical line
+ 'E129,' # visually indented line with same indent as next logical line
+ 'E131,' # continuation line unaligned for hanging indent
+ 'E133,' # closing bracket is missing indentation
+ 'E223,' # tab before operator
+ 'E224,' # tab after operator
+ 'E242,' # tab after ','
+ 'E266,' # too many leading '#' for block comment
+ 'E271,' # multiple spaces after keyword
+ 'E272,' # multiple spaces before keyword
+ 'E273,' # tab after keyword
+ 'E274,' # tab before keyword
+ 'E275,' # missing whitespace after keyword
+ 'E304,' # blank lines found after function decorator
+ 'E306,' # expected 1 blank line before a nested definition
+ 'E401,' # multiple imports on one line
+ 'E402,' # module level import not at top of file
+ 'E502,' # the backslash is redundant between brackets
+ 'E701,' # multiple statements on one line (colon)
+ 'E702,' # multiple statements on one line (semicolon)
+ 'E703,' # statement ends with a semicolon
+ 'E711,' # comparison to None should be 'if cond is None:'
+ 'E714,' # test for object identity should be "is not"
+ 'E721,' # do not compare types, use "isinstance()"
+ 'E742,' # do not define classes named "l", "O", or "I"
+ 'E743,' # do not define functions named "l", "O", or "I"
+ 'E901,' # SyntaxError: invalid syntax
+ 'E902,' # TokenError: EOF in multi-line string
+ 'F401,' # module imported but unused
+ 'F402,' # import module from line N shadowed by loop variable
+ 'F403,' # 'from foo_module import *' used; unable to detect undefined names
+ 'F404,' # future import(s) name after other statements
+ 'F405,' # foo_function may be undefined, or defined from star imports: bar_module
+ 'F406,' # "from module import *" only allowed at module level
+ 'F407,' # an undefined __future__ feature name was imported
+ 'F601,' # dictionary key name repeated with different values
+ 'F602,' # dictionary key variable name repeated with different values
+ 'F621,' # too many expressions in an assignment with star-unpacking
+ 'F622,' # two or more starred expressions in an assignment (a, *b, *c = d)
+ 'F631,' # assertion test is a tuple, which are always True
+ 'F632,' # use ==/!= to compare str, bytes, and int literals
+ 'F701,' # a break statement outside of a while or for loop
+ 'F702,' # a continue statement outside of a while or for loop
+ 'F703,' # a continue statement in a finally block in a loop
+ 'F704,' # a yield or yield from statement outside of a function
+ 'F705,' # a return statement with arguments inside a generator
+ 'F706,' # a return statement outside of a function/method
+ 'F707,' # an except: block as not the last exception handler
+ 'F811,' # redefinition of unused name from line N
+ 'F812,' # list comprehension redefines 'foo' from line N
+ 'F821,' # undefined name 'Foo'
+ 'F822,' # undefined name name in __all__
+ 'F823,' # local variable name … referenced before assignment
+ 'F831,' # duplicate argument name in function definition
+ 'F841,' # local variable 'foo' is assigned to but never used
+ 'W191,' # indentation contains tabs
+ 'W291,' # trailing whitespace
+ 'W292,' # no newline at end of file
+ 'W293,' # blank line contains whitespace
+ 'W601,' # .has_key() is deprecated, use "in"
+ 'W602,' # deprecated form of raising exception
+ 'W603,' # "<>" is deprecated, use "!="
+ 'W604,' # backticks are deprecated, use "repr()"
+ 'W605,' # invalid escape sequence "x"
+ 'W606,' # 'async' and 'await' are reserved keywords starting with Python 3.7
+)
+
+
+def check_dependencies():
+ working_set = {pkg.key for pkg in pkg_resources.working_set}
+
+ for dep in DEPS:
+ if dep not in working_set:
+ print(f"Skipping Python linting since {dep} is not installed.")
+ exit(0)
+
+
+def main():
+ check_dependencies()
+
+ if len(sys.argv) > 1:
+ flake8_files = sys.argv[1:]
+ else:
+ files_args = ['git', 'ls-files', '*.py']
+ flake8_files = subprocess.check_output(files_args).decode("utf-8").splitlines()
+
+ flake8_args = ['flake8', '--ignore=B,C,E,F,I,N,W', f'--select={ENABLED}'] + flake8_files
+ flake8_env = os.environ.copy()
+ flake8_env["PYTHONWARNINGS"] = "ignore"
+
+ try:
+ subprocess.check_call(flake8_args, env=flake8_env)
+ except subprocess.CalledProcessError:
+ exit(1)
+
+ mypy_files = subprocess.check_output(FILES_ARGS).decode("utf-8").splitlines()
+ mypy_args = ['mypy', '--show-error-codes'] + mypy_files
+
+ try:
+ subprocess.check_call(mypy_args)
+ except subprocess.CalledProcessError:
+ exit(1)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/test/lint/lint-python.sh b/test/lint/lint-python.sh
deleted file mode 100755
index 7d7857d325..0000000000
--- a/test/lint/lint-python.sh
+++ /dev/null
@@ -1,111 +0,0 @@
-#!/usr/bin/env bash
-#
-# Copyright (c) 2017-2021 The Bitcoin Core developers
-# Distributed under the MIT software license, see the accompanying
-# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#
-# Check for specified flake8 warnings in python files.
-
-export LC_ALL=C
-export MYPY_CACHE_DIR="${BASE_ROOT_DIR}/test/.mypy_cache"
-
-enabled=(
- E101 # indentation contains mixed spaces and tabs
- E112 # expected an indented block
- E113 # unexpected indentation
- E115 # expected an indented block (comment)
- E116 # unexpected indentation (comment)
- E125 # continuation line with same indent as next logical line
- E129 # visually indented line with same indent as next logical line
- E131 # continuation line unaligned for hanging indent
- E133 # closing bracket is missing indentation
- E223 # tab before operator
- E224 # tab after operator
- E242 # tab after ','
- E266 # too many leading '#' for block comment
- E271 # multiple spaces after keyword
- E272 # multiple spaces before keyword
- E273 # tab after keyword
- E274 # tab before keyword
- E275 # missing whitespace after keyword
- E304 # blank lines found after function decorator
- E306 # expected 1 blank line before a nested definition
- E401 # multiple imports on one line
- E402 # module level import not at top of file
- E502 # the backslash is redundant between brackets
- E701 # multiple statements on one line (colon)
- E702 # multiple statements on one line (semicolon)
- E703 # statement ends with a semicolon
- E711 # comparison to None should be 'if cond is None:'
- E714 # test for object identity should be "is not"
- E721 # do not compare types, use "isinstance()"
- E742 # do not define classes named "l", "O", or "I"
- E743 # do not define functions named "l", "O", or "I"
- E901 # SyntaxError: invalid syntax
- E902 # TokenError: EOF in multi-line string
- F401 # module imported but unused
- F402 # import module from line N shadowed by loop variable
- F403 # 'from foo_module import *' used; unable to detect undefined names
- F404 # future import(s) name after other statements
- F405 # foo_function may be undefined, or defined from star imports: bar_module
- F406 # "from module import *" only allowed at module level
- F407 # an undefined __future__ feature name was imported
- F601 # dictionary key name repeated with different values
- F602 # dictionary key variable name repeated with different values
- F621 # too many expressions in an assignment with star-unpacking
- F622 # two or more starred expressions in an assignment (a, *b, *c = d)
- F631 # assertion test is a tuple, which are always True
- F632 # use ==/!= to compare str, bytes, and int literals
- F701 # a break statement outside of a while or for loop
- F702 # a continue statement outside of a while or for loop
- F703 # a continue statement in a finally block in a loop
- F704 # a yield or yield from statement outside of a function
- F705 # a return statement with arguments inside a generator
- F706 # a return statement outside of a function/method
- F707 # an except: block as not the last exception handler
- F811 # redefinition of unused name from line N
- F812 # list comprehension redefines 'foo' from line N
- F821 # undefined name 'Foo'
- F822 # undefined name name in __all__
- F823 # local variable name … referenced before assignment
- F831 # duplicate argument name in function definition
- F841 # local variable 'foo' is assigned to but never used
- W191 # indentation contains tabs
- W291 # trailing whitespace
- W292 # no newline at end of file
- W293 # blank line contains whitespace
- W601 # .has_key() is deprecated, use "in"
- W602 # deprecated form of raising exception
- W603 # "<>" is deprecated, use "!="
- W604 # backticks are deprecated, use "repr()"
- W605 # invalid escape sequence "x"
- W606 # 'async' and 'await' are reserved keywords starting with Python 3.7
-)
-
-if ! command -v flake8 > /dev/null; then
- echo "Skipping Python linting since flake8 is not installed."
- exit 0
-elif PYTHONWARNINGS="ignore" flake8 --version | grep -q "Python 2"; then
- echo "Skipping Python linting since flake8 is running under Python 2. Install the Python 3 version of flake8."
- exit 0
-fi
-
-EXIT_CODE=0
-
-# shellcheck disable=SC2046
-if ! PYTHONWARNINGS="ignore" flake8 --ignore=B,C,E,F,I,N,W --select=$(IFS=","; echo "${enabled[*]}") $(
- if [[ $# == 0 ]]; then
- git ls-files "*.py"
- else
- echo "$@"
- fi
-); then
- EXIT_CODE=1
-fi
-
-mapfile -t FILES < <(git ls-files "test/functional/*.py" "contrib/devtools/*.py")
-if ! mypy --show-error-codes "${FILES[@]}"; then
- EXIT_CODE=1
-fi
-
-exit $EXIT_CODE
diff --git a/test/lint/lint-whitespace.py b/test/lint/lint-whitespace.py
new file mode 100755
index 0000000000..d98fc8d9a2
--- /dev/null
+++ b/test/lint/lint-whitespace.py
@@ -0,0 +1,135 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2017-2022 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#
+# Check for new lines in diff that introduce trailing whitespace or
+# tab characters instead of spaces.
+
+# We can't run this check unless we know the commit range for the PR.
+
+import argparse
+import os
+import re
+import sys
+
+from subprocess import check_output
+
+EXCLUDED_DIRS = ["depends/patches/",
+ "contrib/guix/patches/",
+ "src/leveldb/",
+ "src/crc32c/",
+ "src/secp256k1/",
+ "src/minisketch/",
+ "src/univalue/",
+ "doc/release-notes/",
+ "src/qt/locale"]
+
+def parse_args():
+ """Parse command line arguments."""
+ parser = argparse.ArgumentParser(
+ description="""
+ Check for new lines in diff that introduce trailing whitespace
+ or tab characters instead of spaces in unstaged changes, the
+ previous n commits, or a commit-range.
+ """,
+ epilog=f"""
+ You can manually set the commit-range with the COMMIT_RANGE
+ environment variable (e.g. "COMMIT_RANGE='47ba2c3...ee50c9e'
+ {sys.argv[0]}"). Defaults to current merge base when neither
+ prev-commits nor the environment variable is set.
+ """)
+
+ parser.add_argument("--prev-commits", "-p", required=False, help="The previous n commits to check")
+
+ return parser.parse_args()
+
+
+def report_diff(selection):
+ filename = ""
+ seen = False
+ seenln = False
+
+ print("The following changes were suspected:")
+
+ for line in selection:
+ if re.match(r"^diff", line):
+ filename = line
+ seen = False
+ elif re.match(r"^@@", line):
+ linenumber = line
+ seenln = False
+ else:
+ if not seen:
+ # The first time a file is seen with trailing whitespace or a tab character, we print the
+ # filename (preceded by a newline).
+ print("")
+ print(filename)
+ seen = True
+ if not seenln:
+ print(linenumber)
+ seenln = True
+ print(line)
+
+
+def get_diff(commit_range, check_only_code):
+ exclude_args = [":(exclude)" + dir for dir in EXCLUDED_DIRS]
+
+ if check_only_code:
+ what_files = ["*.cpp", "*.h", "*.md", "*.py", "*.sh"]
+ else:
+ what_files = ["."]
+
+ diff = check_output(["git", "diff", "-U0", commit_range, "--"] + what_files + exclude_args, universal_newlines=True, encoding="utf8")
+
+ return diff
+
+
+def main():
+ args = parse_args()
+
+ if not os.getenv("COMMIT_RANGE"):
+ if args.prev_commits:
+ commit_range = "HEAD~" + args.prev_commits + "...HEAD"
+ else:
+ # This assumes that the target branch of the pull request will be master.
+ merge_base = check_output(["git", "merge-base", "HEAD", "master"], universal_newlines=True, encoding="utf8").rstrip("\n")
+ commit_range = merge_base + "..HEAD"
+ else:
+ commit_range = os.getenv("COMMIT_RANGE")
+
+ whitespace_selection = []
+ tab_selection = []
+
+ # Check if trailing whitespace was found in the diff.
+ for line in get_diff(commit_range, check_only_code=False).splitlines():
+ if re.match(r"^(diff --git|\@@|^\+.*\s+$)", line):
+ whitespace_selection.append(line)
+
+ whitespace_additions = [i for i in whitespace_selection if i.startswith("+")]
+
+ # Check if tab characters were found in the diff.
+ for line in get_diff(commit_range, check_only_code=True).splitlines():
+ if re.match(r"^(diff --git|\@@|^\+.*\t)", line):
+ tab_selection.append(line)
+
+ tab_additions = [i for i in tab_selection if i.startswith("+")]
+
+ ret = 0
+
+ if len(whitespace_additions) > 0:
+ print("This diff appears to have added new lines with trailing whitespace.")
+ report_diff(whitespace_selection)
+ ret = 1
+
+ if len(tab_additions) > 0:
+ print("This diff appears to have added new lines with tab characters instead of spaces.")
+ report_diff(tab_selection)
+ ret = 1
+
+ sys.exit(ret)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/test/lint/lint-whitespace.sh b/test/lint/lint-whitespace.sh
deleted file mode 100755
index 9d55c71eb5..0000000000
--- a/test/lint/lint-whitespace.sh
+++ /dev/null
@@ -1,115 +0,0 @@
-#!/usr/bin/env bash
-#
-# Copyright (c) 2017-2021 The Bitcoin Core developers
-# Distributed under the MIT software license, see the accompanying
-# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#
-# Check for new lines in diff that introduce trailing whitespace.
-
-# We can't run this check unless we know the commit range for the PR.
-
-export LC_ALL=C
-while getopts "?" opt; do
- case $opt in
- ?)
- echo "Usage: $0 [N]"
- echo " COMMIT_RANGE='<commit range>' $0"
- echo " $0 -?"
- echo "Checks unstaged changes, the previous N commits, or a commit range."
- echo "COMMIT_RANGE='47ba2c3...ee50c9e' $0"
- exit 0
- ;;
- esac
-done
-
-if [ -z "${COMMIT_RANGE}" ]; then
- if [ -n "$1" ]; then
- COMMIT_RANGE="HEAD~$1...HEAD"
- else
- # This assumes that the target branch of the pull request will be master.
- MERGE_BASE=$(git merge-base HEAD master)
- COMMIT_RANGE="$MERGE_BASE..HEAD"
- fi
-fi
-
-showdiff() {
- if ! git diff -U0 "${COMMIT_RANGE}" -- "." ":(exclude)depends/patches/" ":(exclude)contrib/guix/patches/" ":(exclude)src/leveldb/" ":(exclude)src/crc32c/" ":(exclude)src/secp256k1/" ":(exclude)src/minisketch/" ":(exclude)src/univalue/" ":(exclude)doc/release-notes/" ":(exclude)src/qt/locale/"; then
- echo "Failed to get a diff"
- exit 1
- fi
-}
-
-showcodediff() {
- if ! git diff -U0 "${COMMIT_RANGE}" -- *.cpp *.h *.md *.py *.sh ":(exclude)src/leveldb/" ":(exclude)src/crc32c/" ":(exclude)src/secp256k1/" ":(exclude)src/minisketch/" ":(exclude)src/univalue/" ":(exclude)doc/release-notes/" ":(exclude)src/qt/locale/"; then
- echo "Failed to get a diff"
- exit 1
- fi
-}
-
-RET=0
-
-# Check if trailing whitespace was found in the diff.
-if showdiff | grep -E -q '^\+.*\s+$'; then
- echo "This diff appears to have added new lines with trailing whitespace."
- echo "The following changes were suspected:"
- FILENAME=""
- SEEN=0
- SEENLN=0
- while read -r line; do
- if [[ "$line" =~ ^diff ]]; then
- FILENAME="$line"
- SEEN=0
- elif [[ "$line" =~ ^@@ ]]; then
- LINENUMBER="$line"
- SEENLN=0
- else
- if [ "$SEEN" -eq 0 ]; then
- # The first time a file is seen with trailing whitespace, we print the
- # filename (preceded by a newline).
- echo
- echo "$FILENAME"
- SEEN=1
- fi
- if [ "$SEENLN" -eq 0 ]; then
- echo "$LINENUMBER"
- SEENLN=1
- fi
- echo "$line"
- fi
- done < <(showdiff | grep -E '^(diff --git |@@|\+.*\s+$)')
- RET=1
-fi
-
-# Check if tab characters were found in the diff.
-if showcodediff | perl -nle '$MATCH++ if m{^\+.*\t}; END{exit 1 unless $MATCH>0}' > /dev/null; then
- echo "This diff appears to have added new lines with tab characters instead of spaces."
- echo "The following changes were suspected:"
- FILENAME=""
- SEEN=0
- SEENLN=0
- while read -r line; do
- if [[ "$line" =~ ^diff ]]; then
- FILENAME="$line"
- SEEN=0
- elif [[ "$line" =~ ^@@ ]]; then
- LINENUMBER="$line"
- SEENLN=0
- else
- if [ "$SEEN" -eq 0 ]; then
- # The first time a file is seen with a tab character, we print the
- # filename (preceded by a newline).
- echo
- echo "$FILENAME"
- SEEN=1
- fi
- if [ "$SEENLN" -eq 0 ]; then
- echo "$LINENUMBER"
- SEENLN=1
- fi
- echo "$line"
- fi
- done < <(showcodediff | perl -nle 'print if m{^(diff --git |@@|\+.*\t)}')
- RET=1
-fi
-
-exit $RET