aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am13
-rwxr-xr-xci/test/00_setup_env_native_multiprocess.sh1
-rw-r--r--configure.ac1
-rwxr-xr-xcontrib/devtools/symbol-check.py6
-rwxr-xr-xcontrib/devtools/test-security-check.py31
-rwxr-xr-xcontrib/devtools/test-symbol-check.py45
-rwxr-xr-xcontrib/devtools/utils.py22
-rwxr-xr-xcontrib/guix/libexec/build.sh7
-rw-r--r--contrib/guix/manifest.scm6
-rw-r--r--contrib/guix/patches/binutils-mingw-w64-disable-flags.patch171
-rw-r--r--src/Makefile.am8
-rw-r--r--src/addrman.cpp32
-rw-r--r--src/addrman.h5
-rw-r--r--src/netaddress.cpp2
-rw-r--r--src/test/addrman_tests.cpp40
-rw-r--r--src/test/fuzz/netaddress.cpp2
-rw-r--r--src/test/serfloat_tests.cpp8
-rw-r--r--src/test/streams_tests.cpp2
-rw-r--r--test/functional/data/invalid_txs.py48
-rwxr-xr-xtest/functional/feature_block.py9
-rwxr-xr-xtest/functional/feature_fee_estimation.py10
-rwxr-xr-xtest/functional/feature_segwit.py52
-rwxr-xr-xtest/functional/feature_taproot.py18
-rwxr-xr-xtest/functional/mempool_accept.py16
-rwxr-xr-xtest/functional/p2p_segwit.py109
-rwxr-xr-xtest/functional/rpc_signrawtransaction.py5
-rw-r--r--test/functional/test_framework/blocktools.py13
-rwxr-xr-xtest/functional/test_framework/wallet_util.py38
-rwxr-xr-xtest/lint/lint-python.sh2
29 files changed, 502 insertions, 220 deletions
diff --git a/Makefile.am b/Makefile.am
index d84dab1842..3ac698b96f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -58,6 +58,7 @@ DIST_SHARE = \
BIN_CHECKS=$(top_srcdir)/contrib/devtools/symbol-check.py \
$(top_srcdir)/contrib/devtools/security-check.py \
+ $(top_srcdir)/contrib/devtools/utils.py \
$(top_srcdir)/contrib/devtools/pixie.py
WINDOWS_PACKAGING = $(top_srcdir)/share/pixmaps/bitcoin.ico \
@@ -366,14 +367,14 @@ clean-local: clean-docs
test-security-check:
if TARGET_DARWIN
- $(AM_V_at) $(PYTHON) $(top_srcdir)/contrib/devtools/test-security-check.py TestSecurityChecks.test_MACHO
- $(AM_V_at) $(PYTHON) $(top_srcdir)/contrib/devtools/test-symbol-check.py TestSymbolChecks.test_MACHO
+ $(AM_V_at) CC='$(CC)' $(PYTHON) $(top_srcdir)/contrib/devtools/test-security-check.py TestSecurityChecks.test_MACHO
+ $(AM_V_at) CC='$(CC)' $(PYTHON) $(top_srcdir)/contrib/devtools/test-symbol-check.py TestSymbolChecks.test_MACHO
endif
if TARGET_WINDOWS
- $(AM_V_at) $(PYTHON) $(top_srcdir)/contrib/devtools/test-security-check.py TestSecurityChecks.test_PE
- $(AM_V_at) $(PYTHON) $(top_srcdir)/contrib/devtools/test-symbol-check.py TestSymbolChecks.test_PE
+ $(AM_V_at) CC='$(CC)' $(PYTHON) $(top_srcdir)/contrib/devtools/test-security-check.py TestSecurityChecks.test_PE
+ $(AM_V_at) CC='$(CC)' $(PYTHON) $(top_srcdir)/contrib/devtools/test-symbol-check.py TestSymbolChecks.test_PE
endif
if TARGET_LINUX
- $(AM_V_at) $(PYTHON) $(top_srcdir)/contrib/devtools/test-security-check.py TestSecurityChecks.test_ELF
- $(AM_V_at) $(PYTHON) $(top_srcdir)/contrib/devtools/test-symbol-check.py TestSymbolChecks.test_ELF
+ $(AM_V_at) CC='$(CC)' $(PYTHON) $(top_srcdir)/contrib/devtools/test-security-check.py TestSecurityChecks.test_ELF
+ $(AM_V_at) CC='$(CC)' CPPFILT='$(CPPFILT)' $(PYTHON) $(top_srcdir)/contrib/devtools/test-symbol-check.py TestSymbolChecks.test_ELF
endif
diff --git a/ci/test/00_setup_env_native_multiprocess.sh b/ci/test/00_setup_env_native_multiprocess.sh
index 1418dfbc51..8869b2a083 100755
--- a/ci/test/00_setup_env_native_multiprocess.sh
+++ b/ci/test/00_setup_env_native_multiprocess.sh
@@ -13,5 +13,4 @@ export DEP_OPTS="DEBUG=1 MULTIPROCESS=1"
export GOAL="install"
export BITCOIN_CONFIG="--enable-debug CC=clang CXX=clang++" # Use clang to avoid OOM
export TEST_RUNNER_ENV="BITCOIND=bitcoin-node"
-export RUN_SECURITY_TESTS="true"
export PIP_PACKAGES="lief"
diff --git a/configure.ac b/configure.ac
index 94f01a51a6..6f78e8dec4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -900,6 +900,7 @@ if test x$use_hardening != xno; then
])
fi
+ AX_CHECK_LINK_FLAG([[-Wl,--enable-reloc-section]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--enable-reloc-section"],, [[$LDFLAG_WERROR]])
AX_CHECK_LINK_FLAG([[-Wl,--dynamicbase]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--dynamicbase"],, [[$LDFLAG_WERROR]])
AX_CHECK_LINK_FLAG([[-Wl,--nxcompat]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--nxcompat"],, [[$LDFLAG_WERROR]])
AX_CHECK_LINK_FLAG([[-Wl,--high-entropy-va]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--high-entropy-va"],, [[$LDFLAG_WERROR]])
diff --git a/contrib/devtools/symbol-check.py b/contrib/devtools/symbol-check.py
index 407c0a2d72..61f727fa63 100755
--- a/contrib/devtools/symbol-check.py
+++ b/contrib/devtools/symbol-check.py
@@ -12,12 +12,13 @@ Example usage:
'''
import subprocess
import sys
-import os
from typing import List, Optional
import lief
import pixie
+from utils import determine_wellknown_cmd
+
# Debian 8 (Jessie) EOL: 2020. https://wiki.debian.org/DebianReleases#Production_Releases
#
# - g++ version 4.9.2 (https://packages.debian.org/search?suite=jessie&arch=any&searchon=names&keywords=g%2B%2B)
@@ -60,7 +61,6 @@ IGNORE_EXPORTS = {
'_edata', '_end', '__end__', '_init', '__bss_start', '__bss_start__', '_bss_end__', '__bss_end__', '_fini', '_IO_stdin_used', 'stdin', 'stdout', 'stderr',
'environ', '_environ', '__environ',
}
-CPPFILT_CMD = os.getenv('CPPFILT', '/usr/bin/c++filt')
# Allowed NEEDED libraries
ELF_ALLOWED_LIBRARIES = {
@@ -140,7 +140,7 @@ class CPPFilt(object):
Use a pipe to the 'c++filt' command.
'''
def __init__(self):
- self.proc = subprocess.Popen(CPPFILT_CMD, stdin=subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines=True)
+ self.proc = subprocess.Popen(determine_wellknown_cmd('CPPFILT', 'c++filt'), stdin=subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines=True)
def __call__(self, mangled):
self.proc.stdin.write(mangled + '\n')
diff --git a/contrib/devtools/test-security-check.py b/contrib/devtools/test-security-check.py
index c079fe5b4d..14058e2cc8 100755
--- a/contrib/devtools/test-security-check.py
+++ b/contrib/devtools/test-security-check.py
@@ -9,6 +9,8 @@ import os
import subprocess
import unittest
+from utils import determine_wellknown_cmd
+
def write_testcode(filename):
with open(filename, 'w', encoding="utf8") as f:
f.write('''
@@ -25,7 +27,7 @@ def clean_files(source, executable):
os.remove(executable)
def call_security_check(cc, source, executable, options):
- subprocess.run([cc,source,'-o',executable] + options, check=True)
+ subprocess.run([*cc,source,'-o',executable] + options, check=True)
p = subprocess.run(['./contrib/devtools/security-check.py',executable], stdout=subprocess.PIPE, universal_newlines=True)
return (p.returncode, p.stdout.rstrip())
@@ -33,7 +35,7 @@ class TestSecurityChecks(unittest.TestCase):
def test_ELF(self):
source = 'test1.c'
executable = 'test1'
- cc = 'gcc'
+ cc = determine_wellknown_cmd('CC', 'gcc')
write_testcode(source)
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-zexecstack','-fno-stack-protector','-Wl,-znorelro','-no-pie','-fno-PIE', '-Wl,-z,separate-code']),
@@ -54,18 +56,20 @@ class TestSecurityChecks(unittest.TestCase):
def test_PE(self):
source = 'test1.c'
executable = 'test1.exe'
- cc = 'x86_64-w64-mingw32-gcc'
+ cc = determine_wellknown_cmd('CC', 'x86_64-w64-mingw32-gcc')
write_testcode(source)
- self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--no-nxcompat','-Wl,--no-dynamicbase','-Wl,--no-high-entropy-va','-no-pie','-fno-PIE']),
- (1, executable+': failed DYNAMIC_BASE HIGH_ENTROPY_VA NX RELOC_SECTION'))
- self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--no-dynamicbase','-Wl,--no-high-entropy-va','-no-pie','-fno-PIE']),
- (1, executable+': failed DYNAMIC_BASE HIGH_ENTROPY_VA RELOC_SECTION'))
- self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--dynamicbase','-Wl,--no-high-entropy-va','-no-pie','-fno-PIE']),
- (1, executable+': failed HIGH_ENTROPY_VA RELOC_SECTION'))
- self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--dynamicbase','-Wl,--high-entropy-va','-no-pie','-fno-PIE']),
- (1, executable+': failed RELOC_SECTION'))
- self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--dynamicbase','-Wl,--high-entropy-va','-pie','-fPIE']),
+ self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--no-nxcompat','-Wl,--disable-reloc-section','-Wl,--no-dynamicbase','-Wl,--no-high-entropy-va','-no-pie','-fno-PIE']),
+ (1, executable+': failed PIE DYNAMIC_BASE HIGH_ENTROPY_VA NX RELOC_SECTION'))
+ self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--disable-reloc-section','-Wl,--no-dynamicbase','-Wl,--no-high-entropy-va','-no-pie','-fno-PIE']),
+ (1, executable+': failed PIE DYNAMIC_BASE HIGH_ENTROPY_VA RELOC_SECTION'))
+ self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--enable-reloc-section','-Wl,--no-dynamicbase','-Wl,--no-high-entropy-va','-no-pie','-fno-PIE']),
+ (1, executable+': failed PIE DYNAMIC_BASE HIGH_ENTROPY_VA'))
+ self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--enable-reloc-section','-Wl,--no-dynamicbase','-Wl,--no-high-entropy-va','-pie','-fPIE']),
+ (1, executable+': failed PIE DYNAMIC_BASE HIGH_ENTROPY_VA')) # -pie -fPIE does nothing unless --dynamicbase is also supplied
+ self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--enable-reloc-section','-Wl,--dynamicbase','-Wl,--no-high-entropy-va','-pie','-fPIE']),
+ (1, executable+': failed HIGH_ENTROPY_VA'))
+ self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--enable-reloc-section','-Wl,--dynamicbase','-Wl,--high-entropy-va','-pie','-fPIE']),
(0, ''))
clean_files(source, executable)
@@ -73,7 +77,7 @@ class TestSecurityChecks(unittest.TestCase):
def test_MACHO(self):
source = 'test1.c'
executable = 'test1'
- cc = 'clang'
+ cc = determine_wellknown_cmd('CC', 'clang')
write_testcode(source)
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-no_pie','-Wl,-flat_namespace','-Wl,-allow_stack_execute','-fno-stack-protector']),
@@ -95,4 +99,3 @@ class TestSecurityChecks(unittest.TestCase):
if __name__ == '__main__':
unittest.main()
-
diff --git a/contrib/devtools/test-symbol-check.py b/contrib/devtools/test-symbol-check.py
index 6ce2fa3560..7d83c5f751 100755
--- a/contrib/devtools/test-symbol-check.py
+++ b/contrib/devtools/test-symbol-check.py
@@ -7,41 +7,51 @@ Test script for symbol-check.py
'''
import os
import subprocess
+from typing import List
import unittest
-def call_symbol_check(cc, source, executable, options):
- subprocess.run([cc,source,'-o',executable] + options, check=True)
+from utils import determine_wellknown_cmd
+
+def call_symbol_check(cc: List[str], source, executable, options):
+ subprocess.run([*cc,source,'-o',executable] + options, check=True)
p = subprocess.run(['./contrib/devtools/symbol-check.py',executable], stdout=subprocess.PIPE, universal_newlines=True)
os.remove(source)
os.remove(executable)
return (p.returncode, p.stdout.rstrip())
+def get_machine(cc: List[str]):
+ p = subprocess.run([*cc,'-dumpmachine'], stdout=subprocess.PIPE, universal_newlines=True)
+ return p.stdout.rstrip()
+
class TestSymbolChecks(unittest.TestCase):
def test_ELF(self):
source = 'test1.c'
executable = 'test1'
- cc = 'gcc'
+ cc = determine_wellknown_cmd('CC', 'gcc')
+
+ # there's no way to do this test for RISC-V at the moment; we build for
+ # RISC-V in a glibc 2.27 envinonment and we allow all symbols from 2.27.
+ if 'riscv' in get_machine(cc):
+ self.skipTest("test not available for RISC-V")
- # renameat2 was introduced in GLIBC 2.28, so is newer than the upper limit
- # of glibc for all platforms
+ # nextup was introduced in GLIBC 2.24, so is newer than our supported
+ # glibc (2.17), and available in our release build environment (2.24).
with open(source, 'w', encoding="utf8") as f:
f.write('''
#define _GNU_SOURCE
- #include <stdio.h>
- #include <linux/fs.h>
+ #include <math.h>
- int renameat2(int olddirfd, const char *oldpath,
- int newdirfd, const char *newpath, unsigned int flags);
+ double nextup(double x);
int main()
{
- renameat2(0, "test", 0, "test_", RENAME_EXCHANGE);
+ nextup(3.14);
return 0;
}
''')
- self.assertEqual(call_symbol_check(cc, source, executable, []),
- (1, executable + ': symbol renameat2 from unsupported version GLIBC_2.28\n' +
+ self.assertEqual(call_symbol_check(cc, source, executable, ['-lm']),
+ (1, executable + ': symbol nextup from unsupported version GLIBC_2.24\n' +
executable + ': failed IMPORTED_SYMBOLS'))
# -lutil is part of the libc6 package so a safe bet that it's installed
@@ -82,7 +92,7 @@ class TestSymbolChecks(unittest.TestCase):
def test_MACHO(self):
source = 'test1.c'
executable = 'test1'
- cc = 'clang'
+ cc = determine_wellknown_cmd('CC', 'clang')
with open(source, 'w', encoding="utf8") as f:
f.write('''
@@ -96,7 +106,7 @@ class TestSymbolChecks(unittest.TestCase):
''')
- self.assertEqual(call_symbol_check(cc, source, executable, ['-lexpat']),
+ self.assertEqual(call_symbol_check(cc, source, executable, ['-lexpat', '-Wl,-platform_version','-Wl,macos', '-Wl,11.4', '-Wl,11.4']),
(1, 'libexpat.1.dylib is not in ALLOWED_LIBRARIES!\n' +
f'{executable}: failed DYNAMIC_LIBRARIES MIN_OS SDK'))
@@ -113,7 +123,7 @@ class TestSymbolChecks(unittest.TestCase):
}
''')
- self.assertEqual(call_symbol_check(cc, source, executable, ['-framework', 'CoreGraphics']),
+ self.assertEqual(call_symbol_check(cc, source, executable, ['-framework', 'CoreGraphics', '-Wl,-platform_version','-Wl,macos', '-Wl,11.4', '-Wl,11.4']),
(1, f'{executable}: failed MIN_OS SDK'))
source = 'test3.c'
@@ -126,13 +136,13 @@ class TestSymbolChecks(unittest.TestCase):
}
''')
- self.assertEqual(call_symbol_check(cc, source, executable, ['-mmacosx-version-min=10.14']),
+ self.assertEqual(call_symbol_check(cc, source, executable, ['-Wl,-platform_version','-Wl,macos', '-Wl,10.14', '-Wl,11.4']),
(1, f'{executable}: failed SDK'))
def test_PE(self):
source = 'test1.c'
executable = 'test1.exe'
- cc = 'x86_64-w64-mingw32-gcc'
+ cc = determine_wellknown_cmd('CC', 'x86_64-w64-mingw32-gcc')
with open(source, 'w', encoding="utf8") as f:
f.write('''
@@ -182,4 +192,3 @@ class TestSymbolChecks(unittest.TestCase):
if __name__ == '__main__':
unittest.main()
-
diff --git a/contrib/devtools/utils.py b/contrib/devtools/utils.py
new file mode 100755
index 0000000000..68ad1c3aba
--- /dev/null
+++ b/contrib/devtools/utils.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python3
+# Copyright (c) 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.
+'''
+Common utility functions
+'''
+import shutil
+import sys
+import os
+from typing import List
+
+
+def determine_wellknown_cmd(envvar, progname) -> List[str]:
+ maybe_env = os.getenv(envvar)
+ maybe_which = shutil.which(progname)
+ if maybe_env:
+ return maybe_env.split(' ') # Well-known vars are often meant to be word-split
+ elif maybe_which:
+ return [ maybe_which ]
+ else:
+ sys.exit(f"{progname} not found")
diff --git a/contrib/guix/libexec/build.sh b/contrib/guix/libexec/build.sh
index 02ef800963..0b96949a6b 100755
--- a/contrib/guix/libexec/build.sh
+++ b/contrib/guix/libexec/build.sh
@@ -299,10 +299,11 @@ mkdir -p "$DISTSRC"
# Build Bitcoin Core
make --jobs="$JOBS" ${V:+V=1}
- # Perform basic ELF security checks on a series of executables.
+ # Check that symbol/security checks tools are sane.
+ make test-security-check ${V:+V=1}
+ # Perform basic security checks on a series of executables.
make -C src --jobs=1 check-security ${V:+V=1}
- # Check that executables only contain allowed gcc, glibc and libstdc++
- # version symbols for Linux distro back-compatibility.
+ # Check that executables only contain allowed version symbols.
make -C src --jobs=1 check-symbols ${V:+V=1}
mkdir -p "$OUTDIR"
diff --git a/contrib/guix/manifest.scm b/contrib/guix/manifest.scm
index f4df4855fc..e71cf52533 100644
--- a/contrib/guix/manifest.scm
+++ b/contrib/guix/manifest.scm
@@ -80,6 +80,10 @@ http://www.linuxfromscratch.org/hlfs/view/development/chapter05/gcc-pass1.html"
(("-rpath=") "-rpath-link="))
#t))))))))
+(define (make-binutils-with-mingw-w64-disable-flags xbinutils)
+ (package-with-extra-patches xbinutils
+ (search-our-patches "binutils-mingw-w64-disable-flags.patch")))
+
(define (make-cross-toolchain target
base-gcc-for-libc
base-kernel-headers
@@ -168,7 +172,7 @@ desirable for building Bitcoin Core release binaries."
(define (make-mingw-pthreads-cross-toolchain target)
"Create a cross-compilation toolchain package for TARGET"
- (let* ((xbinutils (cross-binutils target))
+ (let* ((xbinutils (make-binutils-with-mingw-w64-disable-flags (cross-binutils target)))
(pthreads-xlibc mingw-w64-x86_64-winpthreads)
(pthreads-xgcc (make-gcc-with-pthreads
(cross-gcc target
diff --git a/contrib/guix/patches/binutils-mingw-w64-disable-flags.patch b/contrib/guix/patches/binutils-mingw-w64-disable-flags.patch
new file mode 100644
index 0000000000..8f88eb9dfd
--- /dev/null
+++ b/contrib/guix/patches/binutils-mingw-w64-disable-flags.patch
@@ -0,0 +1,171 @@
+Description: Add disable opposites to the security-related flags
+Author: Stephen Kitt <skitt@debian.org>
+
+This patch adds "no-" variants to disable the various security flags:
+"no-dynamicbase", "no-nxcompat", "no-high-entropy-va", "disable-reloc-section".
+
+--- a/ld/emultempl/pe.em
++++ b/ld/emultempl/pe.em
+@@ -259,9 +261,11 @@
+ (OPTION_ENABLE_LONG_SECTION_NAMES + 1)
+ /* DLLCharacteristics flags. */
+ #define OPTION_DYNAMIC_BASE (OPTION_DISABLE_LONG_SECTION_NAMES + 1)
+-#define OPTION_FORCE_INTEGRITY (OPTION_DYNAMIC_BASE + 1)
++#define OPTION_NO_DYNAMIC_BASE (OPTION_DYNAMIC_BASE + 1)
++#define OPTION_FORCE_INTEGRITY (OPTION_NO_DYNAMIC_BASE + 1)
+ #define OPTION_NX_COMPAT (OPTION_FORCE_INTEGRITY + 1)
+-#define OPTION_NO_ISOLATION (OPTION_NX_COMPAT + 1)
++#define OPTION_NO_NX_COMPAT (OPTION_NX_COMPAT + 1)
++#define OPTION_NO_ISOLATION (OPTION_NO_NX_COMPAT + 1)
+ #define OPTION_NO_SEH (OPTION_NO_ISOLATION + 1)
+ #define OPTION_NO_BIND (OPTION_NO_SEH + 1)
+ #define OPTION_WDM_DRIVER (OPTION_NO_BIND + 1)
+@@ -271,6 +275,7 @@
+ #define OPTION_NO_INSERT_TIMESTAMP (OPTION_INSERT_TIMESTAMP + 1)
+ #define OPTION_BUILD_ID (OPTION_NO_INSERT_TIMESTAMP + 1)
+ #define OPTION_ENABLE_RELOC_SECTION (OPTION_BUILD_ID + 1)
++#define OPTION_DISABLE_RELOC_SECTION (OPTION_ENABLE_RELOC_SECTION + 1)
+
+ static void
+ gld${EMULATION_NAME}_add_options
+@@ -342,8 +347,10 @@
+ {"enable-long-section-names", no_argument, NULL, OPTION_ENABLE_LONG_SECTION_NAMES},
+ {"disable-long-section-names", no_argument, NULL, OPTION_DISABLE_LONG_SECTION_NAMES},
+ {"dynamicbase",no_argument, NULL, OPTION_DYNAMIC_BASE},
++ {"no-dynamicbase", no_argument, NULL, OPTION_NO_DYNAMIC_BASE},
+ {"forceinteg", no_argument, NULL, OPTION_FORCE_INTEGRITY},
+ {"nxcompat", no_argument, NULL, OPTION_NX_COMPAT},
++ {"no-nxcompat", no_argument, NULL, OPTION_NO_NX_COMPAT},
+ {"no-isolation", no_argument, NULL, OPTION_NO_ISOLATION},
+ {"no-seh", no_argument, NULL, OPTION_NO_SEH},
+ {"no-bind", no_argument, NULL, OPTION_NO_BIND},
+@@ -351,6 +358,7 @@
+ {"tsaware", no_argument, NULL, OPTION_TERMINAL_SERVER_AWARE},
+ {"build-id", optional_argument, NULL, OPTION_BUILD_ID},
+ {"enable-reloc-section", no_argument, NULL, OPTION_ENABLE_RELOC_SECTION},
++ {"disable-reloc-section", no_argument, NULL, OPTION_DISABLE_RELOC_SECTION},
+ {NULL, no_argument, NULL, 0}
+ };
+
+@@ -485,9 +494,12 @@
+ in object files\n"));
+ fprintf (file, _(" --dynamicbase Image base address may be relocated using\n\
+ address space layout randomization (ASLR)\n"));
++ fprintf (file, _(" --no-dynamicbase Image base address may not be relocated\n"));
+ fprintf (file, _(" --enable-reloc-section Create the base relocation table\n"));
++ fprintf (file, _(" --disable-reloc-section Disable the base relocation table\n"));
+ fprintf (file, _(" --forceinteg Code integrity checks are enforced\n"));
+ fprintf (file, _(" --nxcompat Image is compatible with data execution prevention\n"));
++ fprintf (file, _(" --no-nxcompat Image is not compatible with data execution prevention\n"));
+ fprintf (file, _(" --no-isolation Image understands isolation but do not isolate the image\n"));
+ fprintf (file, _(" --no-seh Image does not use SEH. No SE handler may\n\
+ be called in this image\n"));
+@@ -862,12 +874,21 @@
+ case OPTION_ENABLE_RELOC_SECTION:
+ pe_dll_enable_reloc_section = 1;
+ break;
++ case OPTION_DISABLE_RELOC_SECTION:
++ pe_dll_enable_reloc_section = 0;
++ /* fall through */
++ case OPTION_NO_DYNAMIC_BASE:
++ pe_dll_characteristics &= ~IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE;
++ break;
+ case OPTION_FORCE_INTEGRITY:
+ pe_dll_characteristics |= IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY;
+ break;
+ case OPTION_NX_COMPAT:
+ pe_dll_characteristics |= IMAGE_DLL_CHARACTERISTICS_NX_COMPAT;
+ break;
++ case OPTION_NO_NX_COMPAT:
++ pe_dll_characteristics &= ~IMAGE_DLL_CHARACTERISTICS_NX_COMPAT;
++ break;
+ case OPTION_NO_ISOLATION:
+ pe_dll_characteristics |= IMAGE_DLLCHARACTERISTICS_NO_ISOLATION;
+ break;
+--- a/ld/emultempl/pep.em
++++ b/ld/emultempl/pep.em
+@@ -237,9 +240,12 @@
+ OPTION_ENABLE_LONG_SECTION_NAMES,
+ OPTION_DISABLE_LONG_SECTION_NAMES,
+ OPTION_HIGH_ENTROPY_VA,
++ OPTION_NO_HIGH_ENTROPY_VA,
+ OPTION_DYNAMIC_BASE,
++ OPTION_NO_DYNAMIC_BASE,
+ OPTION_FORCE_INTEGRITY,
+ OPTION_NX_COMPAT,
++ OPTION_NO_NX_COMPAT,
+ OPTION_NO_ISOLATION,
+ OPTION_NO_SEH,
+ OPTION_NO_BIND,
+@@ -248,7 +254,8 @@
+ OPTION_NO_INSERT_TIMESTAMP,
+ OPTION_TERMINAL_SERVER_AWARE,
+ OPTION_BUILD_ID,
+- OPTION_ENABLE_RELOC_SECTION
++ OPTION_ENABLE_RELOC_SECTION,
++ OPTION_DISABLE_RELOC_SECTION
+ };
+
+ static void
+@@ -315,9 +322,12 @@
+ {"enable-long-section-names", no_argument, NULL, OPTION_ENABLE_LONG_SECTION_NAMES},
+ {"disable-long-section-names", no_argument, NULL, OPTION_DISABLE_LONG_SECTION_NAMES},
+ {"high-entropy-va", no_argument, NULL, OPTION_HIGH_ENTROPY_VA},
++ {"no-high-entropy-va", no_argument, NULL, OPTION_NO_HIGH_ENTROPY_VA},
+ {"dynamicbase",no_argument, NULL, OPTION_DYNAMIC_BASE},
++ {"no-dynamicbase", no_argument, NULL, OPTION_NO_DYNAMIC_BASE},
+ {"forceinteg", no_argument, NULL, OPTION_FORCE_INTEGRITY},
+ {"nxcompat", no_argument, NULL, OPTION_NX_COMPAT},
++ {"no-nxcompat", no_argument, NULL, OPTION_NO_NX_COMPAT},
+ {"no-isolation", no_argument, NULL, OPTION_NO_ISOLATION},
+ {"no-seh", no_argument, NULL, OPTION_NO_SEH},
+ {"no-bind", no_argument, NULL, OPTION_NO_BIND},
+@@ -327,6 +337,7 @@
+ {"no-insert-timestamp", no_argument, NULL, OPTION_NO_INSERT_TIMESTAMP},
+ {"build-id", optional_argument, NULL, OPTION_BUILD_ID},
+ {"enable-reloc-section", no_argument, NULL, OPTION_ENABLE_RELOC_SECTION},
++ {"disable-reloc-section", no_argument, NULL, OPTION_DISABLE_RELOC_SECTION},
+ {NULL, no_argument, NULL, 0}
+ };
+
+@@ -448,11 +461,15 @@
+ in object files\n"));
+ fprintf (file, _(" --high-entropy-va Image is compatible with 64-bit address space\n\
+ layout randomization (ASLR)\n"));
++ fprintf (file, _(" --no-high-entropy-va Image is not compatible with 64-bit ASLR\n"));
+ fprintf (file, _(" --dynamicbase Image base address may be relocated using\n\
+ address space layout randomization (ASLR)\n"));
++ fprintf (file, _(" --no-dynamicbase Image base address may not be relocated\n"));
+ fprintf (file, _(" --enable-reloc-section Create the base relocation table\n"));
++ fprintf (file, _(" --disable-reloc-section Disable the base relocation table\n"));
+ fprintf (file, _(" --forceinteg Code integrity checks are enforced\n"));
+ fprintf (file, _(" --nxcompat Image is compatible with data execution prevention\n"));
++ fprintf (file, _(" --no-nxcompat Image is not compatible with data execution prevention\n"));
+ fprintf (file, _(" --no-isolation Image understands isolation but do not isolate the image\n"));
+ fprintf (file, _(" --no-seh Image does not use SEH; no SE handler may\n\
+ be called in this image\n"));
+@@ -809,12 +826,24 @@
+ case OPTION_ENABLE_RELOC_SECTION:
+ pep_dll_enable_reloc_section = 1;
+ break;
++ case OPTION_DISABLE_RELOC_SECTION:
++ pep_dll_enable_reloc_section = 0;
++ /* fall through */
++ case OPTION_NO_DYNAMIC_BASE:
++ pe_dll_characteristics &= ~IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE;
++ /* fall through */
++ case OPTION_NO_HIGH_ENTROPY_VA:
++ pe_dll_characteristics &= ~IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA;
++ break;
+ case OPTION_FORCE_INTEGRITY:
+ pe_dll_characteristics |= IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY;
+ break;
+ case OPTION_NX_COMPAT:
+ pe_dll_characteristics |= IMAGE_DLL_CHARACTERISTICS_NX_COMPAT;
+ break;
++ case OPTION_NO_NX_COMPAT:
++ pe_dll_characteristics &= ~IMAGE_DLL_CHARACTERISTICS_NX_COMPAT;
++ break;
+ case OPTION_NO_ISOLATION:
+ pe_dll_characteristics |= IMAGE_DLLCHARACTERISTICS_NO_ISOLATION;
+ break;
diff --git a/src/Makefile.am b/src/Makefile.am
index 9430b778f0..7de5fb36ed 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -814,23 +814,23 @@ clean-local:
check-symbols: $(bin_PROGRAMS)
if TARGET_DARWIN
@echo "Checking macOS dynamic libraries..."
- $(AM_V_at) OTOOL=$(OTOOL) $(PYTHON) $(top_srcdir)/contrib/devtools/symbol-check.py $(bin_PROGRAMS)
+ $(AM_V_at) $(PYTHON) $(top_srcdir)/contrib/devtools/symbol-check.py $(bin_PROGRAMS)
endif
if TARGET_WINDOWS
@echo "Checking Windows dynamic libraries..."
- $(AM_V_at) OBJDUMP=$(OBJDUMP) $(PYTHON) $(top_srcdir)/contrib/devtools/symbol-check.py $(bin_PROGRAMS)
+ $(AM_V_at) $(PYTHON) $(top_srcdir)/contrib/devtools/symbol-check.py $(bin_PROGRAMS)
endif
if TARGET_LINUX
@echo "Checking glibc back compat..."
- $(AM_V_at) CPPFILT=$(CPPFILT) $(PYTHON) $(top_srcdir)/contrib/devtools/symbol-check.py $(bin_PROGRAMS)
+ $(AM_V_at) CPPFILT='$(CPPFILT)' $(PYTHON) $(top_srcdir)/contrib/devtools/symbol-check.py $(bin_PROGRAMS)
endif
check-security: $(bin_PROGRAMS)
if HARDEN
@echo "Checking binary security..."
- $(AM_V_at) OBJDUMP=$(OBJDUMP) OTOOL=$(OTOOL) $(PYTHON) $(top_srcdir)/contrib/devtools/security-check.py $(bin_PROGRAMS)
+ $(AM_V_at) $(PYTHON) $(top_srcdir)/contrib/devtools/security-check.py $(bin_PROGRAMS)
endif
libbitcoin_ipc_mpgen_input = \
diff --git a/src/addrman.cpp b/src/addrman.cpp
index 8f702b5a8c..8192b4eba6 100644
--- a/src/addrman.cpp
+++ b/src/addrman.cpp
@@ -77,6 +77,38 @@ double CAddrInfo::GetChance(int64_t nNow) const
return fChance;
}
+void CAddrMan::RemoveInvalid()
+{
+ for (size_t bucket = 0; bucket < ADDRMAN_NEW_BUCKET_COUNT; ++bucket) {
+ for (size_t i = 0; i < ADDRMAN_BUCKET_SIZE; ++i) {
+ const auto id = vvNew[bucket][i];
+ if (id != -1 && !mapInfo[id].IsValid()) {
+ ClearNew(bucket, i);
+ }
+ }
+ }
+
+ for (size_t bucket = 0; bucket < ADDRMAN_TRIED_BUCKET_COUNT; ++bucket) {
+ for (size_t i = 0; i < ADDRMAN_BUCKET_SIZE; ++i) {
+ const auto id = vvTried[bucket][i];
+ if (id == -1) {
+ continue;
+ }
+ const auto& addr_info = mapInfo[id];
+ if (addr_info.IsValid()) {
+ continue;
+ }
+ vvTried[bucket][i] = -1;
+ --nTried;
+ SwapRandom(addr_info.nRandomPos, vRandom.size() - 1);
+ vRandom.pop_back();
+ mapAddr.erase(addr_info);
+ mapInfo.erase(id);
+ m_tried_collisions.erase(id);
+ }
+ }
+}
+
CAddrInfo* CAddrMan::Find(const CNetAddr& addr, int* pnId)
{
AssertLockHeld(cs);
diff --git a/src/addrman.h b/src/addrman.h
index 665e253192..c2f425f2fa 100644
--- a/src/addrman.h
+++ b/src/addrman.h
@@ -450,6 +450,8 @@ public:
LogPrint(BCLog::ADDRMAN, "addrman lost %i new and %i tried addresses due to collisions\n", nLostUnk, nLost);
}
+ RemoveInvalid();
+
Check();
}
@@ -762,6 +764,9 @@ private:
//! Update an entry's service bits.
void SetServices_(const CService &addr, ServiceFlags nServices) EXCLUSIVE_LOCKS_REQUIRED(cs);
+ //! Remove invalid addresses.
+ void RemoveInvalid() EXCLUSIVE_LOCKS_REQUIRED(cs);
+
friend class CAddrManTest;
};
diff --git a/src/netaddress.cpp b/src/netaddress.cpp
index 1ea3969978..e7b3377475 100644
--- a/src/netaddress.cpp
+++ b/src/netaddress.cpp
@@ -489,7 +489,7 @@ bool CNetAddr::IsValid() const
*/
bool CNetAddr::IsRoutable() const
{
- return IsValid() && !(IsRFC1918() || IsRFC2544() || IsRFC3927() || IsRFC4862() || IsRFC6598() || IsRFC5737() || (IsRFC4193() && !IsTor()) || IsRFC4843() || IsRFC7343() || IsLocal() || IsInternal());
+ return IsValid() && !(IsRFC1918() || IsRFC2544() || IsRFC3927() || IsRFC4862() || IsRFC6598() || IsRFC5737() || IsRFC4193() || IsRFC4843() || IsRFC7343() || IsLocal() || IsInternal());
}
/**
diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp
index eb5c37b34d..1103292c1a 100644
--- a/src/test/addrman_tests.cpp
+++ b/src/test/addrman_tests.cpp
@@ -783,6 +783,46 @@ BOOST_AUTO_TEST_CASE(addrman_serialization)
BOOST_CHECK(bucketAndEntry_asmap1_deser_addr1.second != bucketAndEntry_asmap1_deser_addr2.second);
}
+BOOST_AUTO_TEST_CASE(remove_invalid)
+{
+ // Confirm that invalid addresses are ignored in unserialization.
+
+ CAddrManTest addrman;
+ CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+
+ const CAddress new1{ResolveService("5.5.5.5"), NODE_NONE};
+ const CAddress new2{ResolveService("6.6.6.6"), NODE_NONE};
+ const CAddress tried1{ResolveService("7.7.7.7"), NODE_NONE};
+ const CAddress tried2{ResolveService("8.8.8.8"), NODE_NONE};
+
+ addrman.Add({new1, tried1, new2, tried2}, CNetAddr{});
+ addrman.Good(tried1);
+ addrman.Good(tried2);
+ BOOST_REQUIRE_EQUAL(addrman.size(), 4);
+
+ stream << addrman;
+
+ const std::string str{stream.str()};
+ size_t pos;
+
+ const char new2_raw[]{6, 6, 6, 6};
+ const uint8_t new2_raw_replacement[]{0, 0, 0, 0}; // 0.0.0.0 is !IsValid()
+ pos = str.find(new2_raw, 0, sizeof(new2_raw));
+ BOOST_REQUIRE(pos != std::string::npos);
+ BOOST_REQUIRE(pos + sizeof(new2_raw_replacement) <= stream.size());
+ memcpy(stream.data() + pos, new2_raw_replacement, sizeof(new2_raw_replacement));
+
+ const char tried2_raw[]{8, 8, 8, 8};
+ const uint8_t tried2_raw_replacement[]{255, 255, 255, 255}; // 255.255.255.255 is !IsValid()
+ pos = str.find(tried2_raw, 0, sizeof(tried2_raw));
+ BOOST_REQUIRE(pos != std::string::npos);
+ BOOST_REQUIRE(pos + sizeof(tried2_raw_replacement) <= stream.size());
+ memcpy(stream.data() + pos, tried2_raw_replacement, sizeof(tried2_raw_replacement));
+
+ addrman.Clear();
+ stream >> addrman;
+ BOOST_CHECK_EQUAL(addrman.size(), 2);
+}
BOOST_AUTO_TEST_CASE(addrman_selecttriedcollision)
{
diff --git a/src/test/fuzz/netaddress.cpp b/src/test/fuzz/netaddress.cpp
index f9d8129ca9..6cb81901cb 100644
--- a/src/test/fuzz/netaddress.cpp
+++ b/src/test/fuzz/netaddress.cpp
@@ -54,7 +54,7 @@ FUZZ_TARGET(netaddress)
(void)net_addr.IsRFC3927();
(void)net_addr.IsRFC3964();
if (net_addr.IsRFC4193()) {
- assert(net_addr.GetNetwork() == Network::NET_ONION || net_addr.GetNetwork() == Network::NET_INTERNAL || net_addr.GetNetwork() == Network::NET_UNROUTABLE);
+ assert(net_addr.GetNetwork() == Network::NET_INTERNAL || net_addr.GetNetwork() == Network::NET_UNROUTABLE);
}
(void)net_addr.IsRFC4380();
(void)net_addr.IsRFC4843();
diff --git a/src/test/serfloat_tests.cpp b/src/test/serfloat_tests.cpp
index 54e07b0f61..7876c0bcda 100644
--- a/src/test/serfloat_tests.cpp
+++ b/src/test/serfloat_tests.cpp
@@ -36,9 +36,9 @@ uint64_t TestDouble(double f) {
} // namespace
BOOST_AUTO_TEST_CASE(double_serfloat_tests) {
- BOOST_CHECK_EQUAL(TestDouble(0.0), 0);
+ BOOST_CHECK_EQUAL(TestDouble(0.0), 0U);
BOOST_CHECK_EQUAL(TestDouble(-0.0), 0x8000000000000000);
- BOOST_CHECK_EQUAL(TestDouble(std::numeric_limits<double>::infinity()), 0x7ff0000000000000);
+ BOOST_CHECK_EQUAL(TestDouble(std::numeric_limits<double>::infinity()), 0x7ff0000000000000U);
BOOST_CHECK_EQUAL(TestDouble(-std::numeric_limits<double>::infinity()), 0xfff0000000000000);
BOOST_CHECK_EQUAL(TestDouble(0.5), 0x3fe0000000000000ULL);
BOOST_CHECK_EQUAL(TestDouble(1.0), 0x3ff0000000000000ULL);
@@ -48,8 +48,8 @@ BOOST_AUTO_TEST_CASE(double_serfloat_tests) {
// Roundtrip test on IEC559-compatible systems
if (std::numeric_limits<double>::is_iec559) {
- BOOST_CHECK_EQUAL(sizeof(double), 8);
- BOOST_CHECK_EQUAL(sizeof(uint64_t), 8);
+ BOOST_CHECK_EQUAL(sizeof(double), 8U);
+ BOOST_CHECK_EQUAL(sizeof(uint64_t), 8U);
// Test extreme values
TestDouble(std::numeric_limits<double>::min());
TestDouble(-std::numeric_limits<double>::min());
diff --git a/src/test/streams_tests.cpp b/src/test/streams_tests.cpp
index 7af2b79f37..acd0151e1a 100644
--- a/src/test/streams_tests.cpp
+++ b/src/test/streams_tests.cpp
@@ -119,7 +119,7 @@ BOOST_AUTO_TEST_CASE(streams_vector_reader_rvalue)
uint32_t varint = 0;
// Deserialize into r-value
reader >> VARINT(varint);
- BOOST_CHECK_EQUAL(varint, 54321);
+ BOOST_CHECK_EQUAL(varint, 54321U);
BOOST_CHECK(reader.empty());
}
diff --git a/test/functional/data/invalid_txs.py b/test/functional/data/invalid_txs.py
index fab921ef19..cde0399d8b 100644
--- a/test/functional/data/invalid_txs.py
+++ b/test/functional/data/invalid_txs.py
@@ -29,27 +29,32 @@ from test_framework.messages import (
CTxOut,
MAX_MONEY,
)
-from test_framework import script as sc
from test_framework.blocktools import create_tx_with_script, MAX_BLOCK_SIGOPS
from test_framework.script import (
CScript,
+ OP_0,
+ OP_2DIV,
+ OP_2MUL,
+ OP_AND,
OP_CAT,
- OP_SUBSTR,
- OP_LEFT,
- OP_RIGHT,
+ OP_CHECKSIG,
+ OP_DIV,
OP_INVERT,
- OP_AND,
+ OP_LEFT,
+ OP_LSHIFT,
+ OP_MOD,
+ OP_MUL,
OP_OR,
+ OP_RIGHT,
+ OP_RSHIFT,
+ OP_SUBSTR,
+ OP_TRUE,
OP_XOR,
- OP_2MUL,
- OP_2DIV,
- OP_MUL,
- OP_DIV,
- OP_MOD,
- OP_LSHIFT,
- OP_RSHIFT
)
-basic_p2sh = sc.CScript([sc.OP_HASH160, sc.hash160(sc.CScript([sc.OP_0])), sc.OP_EQUAL])
+from test_framework.script_util import (
+ script_to_p2sh_script,
+)
+basic_p2sh = script_to_p2sh_script(CScript([OP_0]))
class BadTxTemplate:
@@ -116,7 +121,7 @@ class SizeTooSmall(BadTxTemplate):
def get_tx(self):
tx = CTransaction()
tx.vin.append(self.valid_txin)
- tx.vout.append(CTxOut(0, sc.CScript([sc.OP_TRUE])))
+ tx.vout.append(CTxOut(0, CScript([OP_TRUE])))
tx.calc_sha256()
return tx
@@ -151,6 +156,19 @@ class DuplicateInput(BadTxTemplate):
return tx
+class PrevoutNullInput(BadTxTemplate):
+ reject_reason = 'bad-txns-prevout-null'
+ expect_disconnect = True
+
+ def get_tx(self):
+ tx = CTransaction()
+ tx.vin.append(self.valid_txin)
+ tx.vin.append(CTxIn(COutPoint(hash=0, n=0xffffffff)))
+ tx.vout.append(CTxOut(1, basic_p2sh))
+ tx.calc_sha256()
+ return tx
+
+
class NonexistentInput(BadTxTemplate):
reject_reason = None # Added as an orphan tx.
expect_disconnect = False
@@ -217,7 +235,7 @@ class TooManySigops(BadTxTemplate):
expect_disconnect = False
def get_tx(self):
- lotsa_checksigs = sc.CScript([sc.OP_CHECKSIG] * (MAX_BLOCK_SIGOPS))
+ lotsa_checksigs = CScript([OP_CHECKSIG] * (MAX_BLOCK_SIGOPS))
return create_tx_with_script(
self.spend_tx, 0,
script_pub_key=lotsa_checksigs,
diff --git a/test/functional/feature_block.py b/test/functional/feature_block.py
index 389db73bc9..c11eabc917 100755
--- a/test/functional/feature_block.py
+++ b/test/functional/feature_block.py
@@ -37,17 +37,17 @@ from test_framework.script import (
OP_CHECKSIGVERIFY,
OP_ELSE,
OP_ENDIF,
- OP_EQUAL,
OP_DROP,
OP_FALSE,
- OP_HASH160,
OP_IF,
OP_INVALIDOPCODE,
OP_RETURN,
OP_TRUE,
SIGHASH_ALL,
LegacySignatureHash,
- hash160,
+)
+from test_framework.script_util import (
+ script_to_p2sh_script,
)
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal
@@ -469,8 +469,7 @@ class FullBlockTest(BitcoinTestFramework):
# Build the redeem script, hash it, use hash to create the p2sh script
redeem_script = CScript([self.coinbase_pubkey] + [OP_2DUP, OP_CHECKSIGVERIFY] * 5 + [OP_CHECKSIG])
- redeem_script_hash = hash160(redeem_script)
- p2sh_script = CScript([OP_HASH160, redeem_script_hash, OP_EQUAL])
+ p2sh_script = script_to_p2sh_script(redeem_script)
# Create a transaction that spends one satoshi to the p2sh_script, the rest to OP_TRUE
# This must be signed because it is spending a coinbase
diff --git a/test/functional/feature_fee_estimation.py b/test/functional/feature_fee_estimation.py
index 8ccdf87ff3..5322b02414 100755
--- a/test/functional/feature_fee_estimation.py
+++ b/test/functional/feature_fee_estimation.py
@@ -18,10 +18,10 @@ from test_framework.script import (
OP_1,
OP_2,
OP_DROP,
- OP_EQUAL,
- OP_HASH160,
OP_TRUE,
- hash160,
+)
+from test_framework.script_util import (
+ script_to_p2sh_script,
)
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
@@ -37,8 +37,8 @@ from test_framework.util import (
# time signing.
REDEEM_SCRIPT_1 = CScript([OP_1, OP_DROP])
REDEEM_SCRIPT_2 = CScript([OP_2, OP_DROP])
-P2SH_1 = CScript([OP_HASH160, hash160(REDEEM_SCRIPT_1), OP_EQUAL])
-P2SH_2 = CScript([OP_HASH160, hash160(REDEEM_SCRIPT_2), OP_EQUAL])
+P2SH_1 = script_to_p2sh_script(REDEEM_SCRIPT_1)
+P2SH_2 = script_to_p2sh_script(REDEEM_SCRIPT_2)
# Associated ScriptSig's to spend satisfy P2SH_1 and P2SH_2
SCRIPT_SIG = [CScript([OP_TRUE, REDEEM_SCRIPT_1]), CScript([OP_TRUE, REDEEM_SCRIPT_2])]
diff --git a/test/functional/feature_segwit.py b/test/functional/feature_segwit.py
index 42910904d7..9cf46d9d11 100755
--- a/test/functional/feature_segwit.py
+++ b/test/functional/feature_segwit.py
@@ -23,7 +23,6 @@ from test_framework.messages import (
CTransaction,
CTxIn,
CTxOut,
- sha256,
tx_from_hex,
)
from test_framework.script import (
@@ -34,12 +33,13 @@ from test_framework.script import (
OP_CHECKMULTISIG,
OP_CHECKSIG,
OP_DROP,
- OP_DUP,
- OP_EQUAL,
- OP_EQUALVERIFY,
- OP_HASH160,
OP_TRUE,
- hash160,
+)
+from test_framework.script_util import (
+ key_to_p2pkh_script,
+ key_to_p2wpkh_script,
+ script_to_p2sh_script,
+ script_to_p2wsh_script,
)
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
@@ -353,7 +353,7 @@ class SegWitTest(BitcoinTestFramework):
multisig_without_privkey_address = self.nodes[0].addmultisigaddress(2, [pubkeys[3], pubkeys[4]])['address']
script = CScript([OP_2, hex_str_to_bytes(pubkeys[3]), hex_str_to_bytes(pubkeys[4]), OP_2, OP_CHECKMULTISIG])
- solvable_after_importaddress.append(CScript([OP_HASH160, hash160(script), OP_EQUAL]))
+ solvable_after_importaddress.append(script_to_p2sh_script(script))
for i in compressed_spendable_address:
v = self.nodes[0].getaddressinfo(i)
@@ -427,10 +427,10 @@ class SegWitTest(BitcoinTestFramework):
op0 = CScript([OP_0])
# 2N7MGY19ti4KDMSzRfPAssP6Pxyuxoi6jLe is the P2SH(P2PKH) version of mjoE3sSrb8ByYEvgnC3Aox86u1CHnfJA4V
unsolvable_address_key = hex_str_to_bytes("02341AEC7587A51CDE5279E0630A531AEA2615A9F80B17E8D9376327BAEAA59E3D")
- unsolvablep2pkh = CScript([OP_DUP, OP_HASH160, hash160(unsolvable_address_key), OP_EQUALVERIFY, OP_CHECKSIG])
- unsolvablep2wshp2pkh = CScript([OP_0, sha256(unsolvablep2pkh)])
- p2shop0 = CScript([OP_HASH160, hash160(op0), OP_EQUAL])
- p2wshop1 = CScript([OP_0, sha256(op1)])
+ unsolvablep2pkh = key_to_p2pkh_script(unsolvable_address_key)
+ unsolvablep2wshp2pkh = script_to_p2wsh_script(unsolvablep2pkh)
+ p2shop0 = script_to_p2sh_script(op0)
+ p2wshop1 = script_to_p2wsh_script(op1)
unsolvable_after_importaddress.append(unsolvablep2pkh)
unsolvable_after_importaddress.append(unsolvablep2wshp2pkh)
unsolvable_after_importaddress.append(op1) # OP_1 will be imported as script
@@ -450,16 +450,16 @@ class SegWitTest(BitcoinTestFramework):
if (v['isscript']):
bare = hex_str_to_bytes(v['hex'])
importlist.append(bare.hex())
- importlist.append(CScript([OP_0, sha256(bare)]).hex())
+ importlist.append(script_to_p2wsh_script(bare).hex())
else:
pubkey = hex_str_to_bytes(v['pubkey'])
p2pk = CScript([pubkey, OP_CHECKSIG])
- p2pkh = CScript([OP_DUP, OP_HASH160, hash160(pubkey), OP_EQUALVERIFY, OP_CHECKSIG])
+ p2pkh = key_to_p2pkh_script(pubkey)
importlist.append(p2pk.hex())
importlist.append(p2pkh.hex())
- importlist.append(CScript([OP_0, hash160(pubkey)]).hex())
- importlist.append(CScript([OP_0, sha256(p2pk)]).hex())
- importlist.append(CScript([OP_0, sha256(p2pkh)]).hex())
+ importlist.append(key_to_p2wpkh_script(pubkey).hex())
+ importlist.append(script_to_p2wsh_script(p2pk).hex())
+ importlist.append(script_to_p2wsh_script(p2pkh).hex())
importlist.append(unsolvablep2pkh.hex())
importlist.append(unsolvablep2wshp2pkh.hex())
@@ -614,22 +614,22 @@ class SegWitTest(BitcoinTestFramework):
def p2sh_address_to_script(self, v):
bare = CScript(hex_str_to_bytes(v['hex']))
p2sh = CScript(hex_str_to_bytes(v['scriptPubKey']))
- p2wsh = CScript([OP_0, sha256(bare)])
- p2sh_p2wsh = CScript([OP_HASH160, hash160(p2wsh), OP_EQUAL])
+ p2wsh = script_to_p2wsh_script(bare)
+ p2sh_p2wsh = script_to_p2sh_script(p2wsh)
return([bare, p2sh, p2wsh, p2sh_p2wsh])
def p2pkh_address_to_script(self, v):
pubkey = hex_str_to_bytes(v['pubkey'])
- p2wpkh = CScript([OP_0, hash160(pubkey)])
- p2sh_p2wpkh = CScript([OP_HASH160, hash160(p2wpkh), OP_EQUAL])
+ p2wpkh = key_to_p2wpkh_script(pubkey)
+ p2sh_p2wpkh = script_to_p2sh_script(p2wpkh)
p2pk = CScript([pubkey, OP_CHECKSIG])
p2pkh = CScript(hex_str_to_bytes(v['scriptPubKey']))
- p2sh_p2pk = CScript([OP_HASH160, hash160(p2pk), OP_EQUAL])
- p2sh_p2pkh = CScript([OP_HASH160, hash160(p2pkh), OP_EQUAL])
- p2wsh_p2pk = CScript([OP_0, sha256(p2pk)])
- p2wsh_p2pkh = CScript([OP_0, sha256(p2pkh)])
- p2sh_p2wsh_p2pk = CScript([OP_HASH160, hash160(p2wsh_p2pk), OP_EQUAL])
- p2sh_p2wsh_p2pkh = CScript([OP_HASH160, hash160(p2wsh_p2pkh), OP_EQUAL])
+ p2sh_p2pk = script_to_p2sh_script(p2pk)
+ p2sh_p2pkh = script_to_p2sh_script(p2pkh)
+ p2wsh_p2pk = script_to_p2wsh_script(p2pk)
+ p2wsh_p2pkh = script_to_p2wsh_script(p2pkh)
+ p2sh_p2wsh_p2pk = script_to_p2sh_script(p2wsh_p2pk)
+ p2sh_p2wsh_p2pkh = script_to_p2sh_script(p2wsh_p2pkh)
return [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh]
def create_and_mine_tx_from_txids(self, txids, success=True):
diff --git a/test/functional/feature_taproot.py b/test/functional/feature_taproot.py
index 99283b69b0..17be29c7bf 100755
--- a/test/functional/feature_taproot.py
+++ b/test/functional/feature_taproot.py
@@ -57,7 +57,6 @@ from test_framework.script import (
OP_ENDIF,
OP_EQUAL,
OP_EQUALVERIFY,
- OP_HASH160,
OP_IF,
OP_NOP,
OP_NOT,
@@ -76,12 +75,17 @@ from test_framework.script import (
is_op_success,
taproot_construct,
)
+from test_framework.script_util import (
+ key_to_p2wpkh_script,
+ keyhash_to_p2pkh_script,
+ script_to_p2sh_script,
+ script_to_p2wsh_script,
+)
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_raises_rpc_error, assert_equal
from test_framework.key import generate_privkey, compute_xonly_pubkey, sign_schnorr, tweak_add_privkey, ECKey
from test_framework.address import (
hash160,
- sha256,
)
from collections import OrderedDict, namedtuple
from io import BytesIO
@@ -458,13 +462,13 @@ def make_spender(comment, *, tap=None, witv0=False, script=None, pkh=None, p2sh=
# P2WPKH
assert script is None
pubkeyhash = hash160(pkh)
- spk = CScript([OP_0, pubkeyhash])
- conf["scriptcode"] = CScript([OP_DUP, OP_HASH160, pubkeyhash, OP_EQUALVERIFY, OP_CHECKSIG])
+ spk = key_to_p2wpkh_script(pkh)
+ conf["scriptcode"] = keyhash_to_p2pkh_script(pubkeyhash)
conf["script_witv0"] = None
conf["inputs"] = [getter("sign"), pkh]
elif script is not None:
# P2WSH
- spk = CScript([OP_0, sha256(script)])
+ spk = script_to_p2wsh_script(script)
conf["scriptcode"] = script
conf["script_witv0"] = script
else:
@@ -475,7 +479,7 @@ def make_spender(comment, *, tap=None, witv0=False, script=None, pkh=None, p2sh=
# P2PKH
assert script is None
pubkeyhash = hash160(pkh)
- spk = CScript([OP_DUP, OP_HASH160, pubkeyhash, OP_EQUALVERIFY, OP_CHECKSIG])
+ spk = keyhash_to_p2pkh_script(pubkeyhash)
conf["scriptcode"] = spk
conf["inputs"] = [getter("sign"), pkh]
elif script is not None:
@@ -496,7 +500,7 @@ def make_spender(comment, *, tap=None, witv0=False, script=None, pkh=None, p2sh=
if p2sh:
# P2SH wrapper can be combined with anything else
conf["script_p2sh"] = spk
- spk = CScript([OP_HASH160, hash160(spk), OP_EQUAL])
+ spk = script_to_p2sh_script(spk)
conf = {**conf, **kwargs}
diff --git a/test/functional/mempool_accept.py b/test/functional/mempool_accept.py
index 1705d957aa..60c0953f6f 100755
--- a/test/functional/mempool_accept.py
+++ b/test/functional/mempool_accept.py
@@ -13,22 +13,24 @@ from test_framework.messages import (
BIP125_SEQUENCE_NUMBER,
COIN,
COutPoint,
+ CTxIn,
CTxOut,
MAX_BLOCK_BASE_SIZE,
MAX_MONEY,
tx_from_hex,
)
from test_framework.script import (
- hash160,
CScript,
OP_0,
OP_2,
OP_3,
OP_CHECKMULTISIG,
- OP_EQUAL,
OP_HASH160,
OP_RETURN,
)
+from test_framework.script_util import (
+ script_to_p2sh_script,
+)
from test_framework.util import (
assert_equal,
assert_raises_rpc_error,
@@ -247,6 +249,14 @@ class MempoolAcceptanceTest(BitcoinTestFramework):
rawtxs=[tx.serialize().hex()],
)
+ self.log.info('A non-coinbase transaction with coinbase-like outpoint')
+ tx = tx_from_hex(raw_tx_reference)
+ tx.vin.append(CTxIn(COutPoint(hash=0, n=0xffffffff)))
+ self.check_mempool_result(
+ result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'bad-txns-prevout-null'}],
+ rawtxs=[tx.serialize().hex()],
+ )
+
self.log.info('A coinbase transaction')
# Pick the input of the first tx we signed, so it has to be a coinbase tx
raw_tx_coinbase_spent = node.getrawtransaction(txid=node.decoderawtransaction(hexstring=raw_tx_in_block)['vin'][0]['txid'])
@@ -291,7 +301,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework):
rawtxs=[tx.serialize().hex()],
)
tx = tx_from_hex(raw_tx_reference)
- output_p2sh_burn = CTxOut(nValue=540, scriptPubKey=CScript([OP_HASH160, hash160(b'burn'), OP_EQUAL]))
+ output_p2sh_burn = CTxOut(nValue=540, scriptPubKey=script_to_p2sh_script(b'burn'))
num_scripts = 100000 // len(output_p2sh_burn.serialize()) # Use enough outputs to make the tx too large for our policy
tx.vout = [output_p2sh_burn] * num_scripts
self.check_mempool_result(
diff --git a/test/functional/p2p_segwit.py b/test/functional/p2p_segwit.py
index 95c7aec318..ead9d852fe 100755
--- a/test/functional/p2p_segwit.py
+++ b/test/functional/p2p_segwit.py
@@ -41,7 +41,6 @@ from test_framework.messages import (
ser_vector,
sha256,
tx_from_hex,
- uint256_from_str,
)
from test_framework.p2p import (
P2PInterface,
@@ -60,12 +59,8 @@ from test_framework.script import (
OP_CHECKMULTISIG,
OP_CHECKSIG,
OP_DROP,
- OP_DUP,
OP_ELSE,
OP_ENDIF,
- OP_EQUAL,
- OP_EQUALVERIFY,
- OP_HASH160,
OP_IF,
OP_RETURN,
OP_TRUE,
@@ -77,6 +72,12 @@ from test_framework.script import (
LegacySignatureHash,
hash160,
)
+from test_framework.script_util import (
+ key_to_p2wpkh_script,
+ keyhash_to_p2pkh_script,
+ script_to_p2sh_script,
+ script_to_p2wsh_script,
+)
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
@@ -100,10 +101,6 @@ class UTXO():
self.n = n
self.nValue = value
-def get_p2pkh_script(pubkeyhash):
- """Get the script associated with a P2PKH."""
- return CScript([CScriptOp(OP_DUP), CScriptOp(OP_HASH160), pubkeyhash, CScriptOp(OP_EQUALVERIFY), CScriptOp(OP_CHECKSIG)])
-
def sign_p2pk_witness_input(script, tx_to, in_idx, hashtype, value, key):
"""Add signature for a P2PK witness program."""
tx_hash = SegwitV0SignatureHash(script, tx_to, in_idx, hashtype, value)
@@ -492,11 +489,8 @@ class SegWitTest(BitcoinTestFramework):
# Create two outputs, a p2wsh and p2sh-p2wsh
witness_program = CScript([OP_TRUE])
- witness_hash = sha256(witness_program)
- script_pubkey = CScript([OP_0, witness_hash])
-
- p2sh_pubkey = hash160(script_pubkey)
- p2sh_script_pubkey = CScript([OP_HASH160, p2sh_pubkey, OP_EQUAL])
+ script_pubkey = script_to_p2wsh_script(witness_program)
+ p2sh_script_pubkey = script_to_p2sh_script(script_pubkey)
value = self.utxo[0].nValue // 3
@@ -631,11 +625,8 @@ class SegWitTest(BitcoinTestFramework):
V0 segwit inputs may only be mined after activation, but not before."""
witness_program = CScript([OP_TRUE])
- witness_hash = sha256(witness_program)
- script_pubkey = CScript([OP_0, witness_hash])
-
- p2sh_pubkey = hash160(witness_program)
- p2sh_script_pubkey = CScript([OP_HASH160, p2sh_pubkey, OP_EQUAL])
+ script_pubkey = script_to_p2wsh_script(witness_program)
+ p2sh_script_pubkey = script_to_p2sh_script(witness_program)
# First prepare a p2sh output (so that spending it will pass standardness)
p2sh_tx = CTransaction()
@@ -662,6 +653,7 @@ class SegWitTest(BitcoinTestFramework):
test_transaction_acceptance(self.nodes[1], self.std_node, tx, with_witness=True, accepted=True)
# Now create something that looks like a P2PKH output. This won't be spendable.
+ witness_hash = sha256(witness_program)
script_pubkey = CScript([OP_0, hash160(witness_hash)])
tx2 = CTransaction()
# tx was accepted, so we spend the second output.
@@ -740,10 +732,8 @@ class SegWitTest(BitcoinTestFramework):
# Prepare the p2sh-wrapped witness output
witness_program = CScript([OP_DROP, OP_TRUE])
- witness_hash = sha256(witness_program)
- p2wsh_pubkey = CScript([OP_0, witness_hash])
- p2sh_witness_hash = hash160(p2wsh_pubkey)
- script_pubkey = CScript([OP_HASH160, p2sh_witness_hash, OP_EQUAL])
+ p2wsh_pubkey = script_to_p2wsh_script(witness_program)
+ script_pubkey = script_to_p2sh_script(p2wsh_pubkey)
script_sig = CScript([p2wsh_pubkey]) # a push of the redeem script
# Fund the P2SH output
@@ -837,8 +827,7 @@ class SegWitTest(BitcoinTestFramework):
# Let's construct a witness program
witness_program = CScript([OP_TRUE])
- witness_hash = sha256(witness_program)
- script_pubkey = CScript([OP_0, witness_hash])
+ script_pubkey = script_to_p2wsh_script(witness_program)
tx.vout.append(CTxOut(self.utxo[0].nValue - 1000, script_pubkey))
tx.rehash()
@@ -951,8 +940,7 @@ class SegWitTest(BitcoinTestFramework):
NUM_OUTPUTS = 50
witness_program = CScript([OP_2DROP] * NUM_DROPS + [OP_TRUE])
- witness_hash = uint256_from_str(sha256(witness_program))
- script_pubkey = CScript([OP_0, ser_uint256(witness_hash)])
+ script_pubkey = script_to_p2wsh_script(witness_program)
prevout = COutPoint(self.utxo[0].sha256, self.utxo[0].n)
value = self.utxo[0].nValue
@@ -1054,8 +1042,7 @@ class SegWitTest(BitcoinTestFramework):
block = self.build_next_block()
witness_program = CScript([OP_DROP, OP_TRUE])
- witness_hash = sha256(witness_program)
- script_pubkey = CScript([OP_0, witness_hash])
+ script_pubkey = script_to_p2wsh_script(witness_program)
# First try extra witness data on a tx that doesn't require a witness
tx = CTransaction()
@@ -1127,8 +1114,7 @@ class SegWitTest(BitcoinTestFramework):
block = self.build_next_block()
witness_program = CScript([OP_DROP, OP_TRUE])
- witness_hash = sha256(witness_program)
- script_pubkey = CScript([OP_0, witness_hash])
+ script_pubkey = script_to_p2wsh_script(witness_program)
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
@@ -1166,8 +1152,7 @@ class SegWitTest(BitcoinTestFramework):
# This program is 19 max pushes (9937 bytes), then 64 more opcode-bytes.
long_witness_program = CScript([b'a' * MAX_SCRIPT_ELEMENT_SIZE] * 19 + [OP_DROP] * 63 + [OP_TRUE])
assert len(long_witness_program) == MAX_PROGRAM_LENGTH + 1
- long_witness_hash = sha256(long_witness_program)
- long_script_pubkey = CScript([OP_0, long_witness_hash])
+ long_script_pubkey = script_to_p2wsh_script(long_witness_program)
block = self.build_next_block()
@@ -1190,8 +1175,7 @@ class SegWitTest(BitcoinTestFramework):
# Try again with one less byte in the witness program
witness_program = CScript([b'a' * MAX_SCRIPT_ELEMENT_SIZE] * 19 + [OP_DROP] * 62 + [OP_TRUE])
assert len(witness_program) == MAX_PROGRAM_LENGTH
- witness_hash = sha256(witness_program)
- script_pubkey = CScript([OP_0, witness_hash])
+ script_pubkey = script_to_p2wsh_script(witness_program)
tx.vout[0] = CTxOut(tx.vout[0].nValue, script_pubkey)
tx.rehash()
@@ -1210,8 +1194,7 @@ class SegWitTest(BitcoinTestFramework):
"""Test that vin length must match vtxinwit length."""
witness_program = CScript([OP_DROP, OP_TRUE])
- witness_hash = sha256(witness_program)
- script_pubkey = CScript([OP_0, witness_hash])
+ script_pubkey = script_to_p2wsh_script(witness_program)
# Create a transaction that splits our utxo into many outputs
tx = CTransaction()
@@ -1318,8 +1301,7 @@ class SegWitTest(BitcoinTestFramework):
# Now try to add extra witness data to a valid witness tx.
witness_program = CScript([OP_TRUE])
- witness_hash = sha256(witness_program)
- script_pubkey = CScript([OP_0, witness_hash])
+ script_pubkey = script_to_p2wsh_script(witness_program)
tx2 = CTransaction()
tx2.vin.append(CTxIn(COutPoint(tx_hash, 0), b""))
tx2.vout.append(CTxOut(tx.vout[0].nValue - 1000, script_pubkey))
@@ -1331,9 +1313,8 @@ class SegWitTest(BitcoinTestFramework):
# Add too-large for IsStandard witness and check that it does not enter reject filter
p2sh_program = CScript([OP_TRUE])
- p2sh_pubkey = hash160(p2sh_program)
witness_program2 = CScript([b'a' * 400000])
- tx3.vout.append(CTxOut(tx2.vout[0].nValue - 1000, CScript([OP_HASH160, p2sh_pubkey, OP_EQUAL])))
+ tx3.vout.append(CTxOut(tx2.vout[0].nValue - 1000, script_to_p2sh_script(p2sh_program)))
tx3.wit.vtxinwit[0].scriptWitness.stack = [witness_program2]
tx3.rehash()
@@ -1482,8 +1463,7 @@ class SegWitTest(BitcoinTestFramework):
block = self.build_next_block()
# Change the output of the block to be a witness output.
witness_program = CScript([OP_TRUE])
- witness_hash = sha256(witness_program)
- script_pubkey = CScript([OP_0, witness_hash])
+ script_pubkey = script_to_p2wsh_script(witness_program)
block.vtx[0].vout[0].scriptPubKey = script_pubkey
# This next line will rehash the coinbase and update the merkle
# root, and solve.
@@ -1530,7 +1510,7 @@ class SegWitTest(BitcoinTestFramework):
# Test 1: P2WPKH
# First create a P2WPKH output that uses an uncompressed pubkey
pubkeyhash = hash160(pubkey)
- script_pkh = CScript([OP_0, pubkeyhash])
+ script_pkh = key_to_p2wpkh_script(pubkey)
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(utxo.sha256, utxo.n), b""))
tx.vout.append(CTxOut(utxo.nValue - 1000, script_pkh))
@@ -1544,13 +1524,12 @@ class SegWitTest(BitcoinTestFramework):
# Now try to spend it. Send it to a P2WSH output, which we'll
# use in the next test.
witness_program = CScript([pubkey, CScriptOp(OP_CHECKSIG)])
- witness_hash = sha256(witness_program)
- script_wsh = CScript([OP_0, witness_hash])
+ script_wsh = script_to_p2wsh_script(witness_program)
tx2 = CTransaction()
tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b""))
tx2.vout.append(CTxOut(tx.vout[0].nValue - 1000, script_wsh))
- script = get_p2pkh_script(pubkeyhash)
+ script = keyhash_to_p2pkh_script(pubkeyhash)
sig_hash = SegwitV0SignatureHash(script, tx2, 0, SIGHASH_ALL, tx.vout[0].nValue)
signature = key.sign_ecdsa(sig_hash) + b'\x01' # 0x1 is SIGHASH_ALL
tx2.wit.vtxinwit.append(CTxInWitness())
@@ -1567,8 +1546,7 @@ class SegWitTest(BitcoinTestFramework):
# Test 2: P2WSH
# Try to spend the P2WSH output created in last test.
# Send it to a P2SH(P2WSH) output, which we'll use in the next test.
- p2sh_witness_hash = hash160(script_wsh)
- script_p2sh = CScript([OP_HASH160, p2sh_witness_hash, OP_EQUAL])
+ script_p2sh = script_to_p2sh_script(script_wsh)
script_sig = CScript([script_wsh])
tx3 = CTransaction()
@@ -1587,7 +1565,7 @@ class SegWitTest(BitcoinTestFramework):
# Test 3: P2SH(P2WSH)
# Try to spend the P2SH output created in the last test.
# Send it to a P2PKH output, which we'll use in the next test.
- script_pubkey = get_p2pkh_script(pubkeyhash)
+ script_pubkey = keyhash_to_p2pkh_script(pubkeyhash)
tx4 = CTransaction()
tx4.vin.append(CTxIn(COutPoint(tx3.sha256, 0), script_sig))
tx4.vout.append(CTxOut(tx3.vout[0].nValue - 1000, script_pubkey))
@@ -1624,8 +1602,7 @@ class SegWitTest(BitcoinTestFramework):
pubkey = key.get_pubkey().get_bytes()
witness_program = CScript([pubkey, CScriptOp(OP_CHECKSIG)])
- witness_hash = sha256(witness_program)
- script_pubkey = CScript([OP_0, witness_hash])
+ script_pubkey = script_to_p2wsh_script(witness_program)
# First create a witness output for use in the tests.
tx = CTransaction()
@@ -1744,7 +1721,7 @@ class SegWitTest(BitcoinTestFramework):
# Now test witness version 0 P2PKH transactions
pubkeyhash = hash160(pubkey)
- script_pkh = CScript([OP_0, pubkeyhash])
+ script_pkh = key_to_p2wpkh_script(pubkey)
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(temp_utxos[0].sha256, temp_utxos[0].n), b""))
tx.vout.append(CTxOut(temp_utxos[0].nValue, script_pkh))
@@ -1754,7 +1731,7 @@ class SegWitTest(BitcoinTestFramework):
tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b""))
tx2.vout.append(CTxOut(tx.vout[0].nValue, CScript([OP_TRUE])))
- script = get_p2pkh_script(pubkeyhash)
+ script = keyhash_to_p2pkh_script(pubkeyhash)
sig_hash = SegwitV0SignatureHash(script, tx2, 0, SIGHASH_ALL, tx.vout[0].nValue)
signature = key.sign_ecdsa(sig_hash) + b'\x01' # 0x1 is SIGHASH_ALL
@@ -1806,8 +1783,7 @@ class SegWitTest(BitcoinTestFramework):
# rules (an anyone-can-spend OP_TRUE would be rejected, if not wrapped
# in P2SH).
p2sh_program = CScript([OP_TRUE])
- p2sh_pubkey = hash160(p2sh_program)
- script_pubkey = CScript([OP_HASH160, p2sh_pubkey, OP_EQUAL])
+ script_pubkey = script_to_p2sh_script(p2sh_program)
# Now check that unnecessary witnesses can't be used to blind a node
# to a transaction, eg by violating standardness checks.
@@ -1872,11 +1848,10 @@ class SegWitTest(BitcoinTestFramework):
# For each script, generate a pair of P2WSH and P2SH-P2WSH output.
outputvalue = (self.utxo[0].nValue - 1000) // (len(scripts) * 2)
for i in scripts:
- p2wsh = CScript([OP_0, sha256(i)])
- p2sh = hash160(p2wsh)
+ p2wsh = script_to_p2wsh_script(i)
p2wsh_scripts.append(p2wsh)
tx.vout.append(CTxOut(outputvalue, p2wsh))
- tx.vout.append(CTxOut(outputvalue, CScript([OP_HASH160, p2sh, OP_EQUAL])))
+ tx.vout.append(CTxOut(outputvalue, script_to_p2sh_script(p2wsh)))
tx.rehash()
txid = tx.sha256
test_transaction_acceptance(self.nodes[0], self.test_node, tx, with_witness=False, accepted=True)
@@ -1890,13 +1865,13 @@ class SegWitTest(BitcoinTestFramework):
for i in range(len(scripts)):
p2wsh_tx = CTransaction()
p2wsh_tx.vin.append(CTxIn(COutPoint(txid, i * 2)))
- p2wsh_tx.vout.append(CTxOut(outputvalue - 5000, CScript([OP_0, hash160(hex_str_to_bytes(""))])))
+ p2wsh_tx.vout.append(CTxOut(outputvalue - 5000, CScript([OP_0, hash160(b"")])))
p2wsh_tx.wit.vtxinwit.append(CTxInWitness())
p2wsh_tx.rehash()
p2wsh_txs.append(p2wsh_tx)
p2sh_tx = CTransaction()
p2sh_tx.vin.append(CTxIn(COutPoint(txid, i * 2 + 1), CScript([p2wsh_scripts[i]])))
- p2sh_tx.vout.append(CTxOut(outputvalue - 5000, CScript([OP_0, hash160(hex_str_to_bytes(""))])))
+ p2sh_tx.vout.append(CTxOut(outputvalue - 5000, CScript([OP_0, hash160(b"")])))
p2sh_tx.wit.vtxinwit.append(CTxInWitness())
p2sh_tx.rehash()
p2sh_txs.append(p2sh_tx)
@@ -1991,8 +1966,7 @@ class SegWitTest(BitcoinTestFramework):
# Keep this under MAX_OPS_PER_SCRIPT (201)
witness_program = CScript([OP_TRUE, OP_IF, OP_TRUE, OP_ELSE] + [OP_CHECKMULTISIG] * 5 + [OP_CHECKSIG] * 193 + [OP_ENDIF])
- witness_hash = sha256(witness_program)
- script_pubkey = CScript([OP_0, witness_hash])
+ script_pubkey = script_to_p2wsh_script(witness_program)
sigops_per_script = 20 * 5 + 193 * 1
# We'll produce 2 extra outputs, one with a program that would take us
@@ -2008,14 +1982,12 @@ class SegWitTest(BitcoinTestFramework):
# N(=MAX_SIGOP_COST//sigops_per_script) outputs of our transaction,
# would push us just over the block sigop limit.
witness_program_toomany = CScript([OP_TRUE, OP_IF, OP_TRUE, OP_ELSE] + [OP_CHECKSIG] * (extra_sigops_available + 1) + [OP_ENDIF])
- witness_hash_toomany = sha256(witness_program_toomany)
- script_pubkey_toomany = CScript([OP_0, witness_hash_toomany])
+ script_pubkey_toomany = script_to_p2wsh_script(witness_program_toomany)
# If we spend this script instead, we would exactly reach our sigop
# limit (for witness sigops).
witness_program_justright = CScript([OP_TRUE, OP_IF, OP_TRUE, OP_ELSE] + [OP_CHECKSIG] * (extra_sigops_available) + [OP_ENDIF])
- witness_hash_justright = sha256(witness_program_justright)
- script_pubkey_justright = CScript([OP_0, witness_hash_justright])
+ script_pubkey_justright = script_to_p2wsh_script(witness_program_justright)
# First split our available utxo into a bunch of outputs
split_value = self.utxo[0].nValue // outputs
@@ -2148,8 +2120,7 @@ class SegWitTest(BitcoinTestFramework):
# Create a Segwit output from the latest UTXO
# and announce it to the network
witness_program = CScript([OP_TRUE])
- witness_hash = sha256(witness_program)
- script_pubkey = CScript([OP_0, witness_hash])
+ script_pubkey = script_to_p2wsh_script(witness_program)
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
diff --git a/test/functional/rpc_signrawtransaction.py b/test/functional/rpc_signrawtransaction.py
index ef5d08e7b9..f3627d1e37 100755
--- a/test/functional/rpc_signrawtransaction.py
+++ b/test/functional/rpc_signrawtransaction.py
@@ -6,7 +6,6 @@
from test_framework.blocktools import COINBASE_MATURITY
from test_framework.address import (
- check_script,
script_to_p2sh,
script_to_p2wsh,
)
@@ -20,12 +19,10 @@ from test_framework.util import (
)
from test_framework.messages import (
CTxInWitness,
- sha256,
tx_from_hex,
)
from test_framework.script import (
CScript,
- OP_0,
OP_CHECKLOCKTIMEVERIFY,
OP_CHECKSIG,
OP_CHECKSEQUENCEVERIFY,
@@ -233,7 +230,7 @@ class SignRawTransactionsTest(BitcoinTestFramework):
'P2PKH': key_to_p2pkh_script(embedded_pubkey).hex(),
'P2PK': CScript([hex_str_to_bytes(embedded_pubkey), OP_CHECKSIG]).hex()
}.get(tx_type, "Invalid tx_type")
- redeem_script = CScript([OP_0, sha256(check_script(witness_script))]).hex()
+ redeem_script = script_to_p2wsh_script(witness_script).hex()
addr = script_to_p2sh(redeem_script)
script_pub_key = self.nodes[1].validateaddress(addr)['scriptPubKey']
# Fund that address
diff --git a/test/functional/test_framework/blocktools.py b/test/functional/test_framework/blocktools.py
index bc43438810..833a215993 100644
--- a/test/functional/test_framework/blocktools.py
+++ b/test/functional/test_framework/blocktools.py
@@ -26,7 +26,6 @@ from .messages import (
hash256,
hex_str_to_bytes,
ser_uint256,
- sha256,
tx_from_hex,
uint256_from_str,
)
@@ -34,13 +33,15 @@ from .script import (
CScript,
CScriptNum,
CScriptOp,
- OP_0,
OP_1,
OP_CHECKMULTISIG,
OP_CHECKSIG,
OP_RETURN,
OP_TRUE,
- hash160,
+)
+from .script_util import (
+ key_to_p2wpkh_script,
+ script_to_p2wsh_script,
)
from .util import assert_equal
@@ -206,13 +207,11 @@ def witness_script(use_p2wsh, pubkey):
scriptPubKey."""
if not use_p2wsh:
# P2WPKH instead
- pubkeyhash = hash160(hex_str_to_bytes(pubkey))
- pkscript = CScript([OP_0, pubkeyhash])
+ pkscript = key_to_p2wpkh_script(pubkey)
else:
# 1-of-1 multisig
witness_program = CScript([OP_1, hex_str_to_bytes(pubkey), OP_1, OP_CHECKMULTISIG])
- scripthash = sha256(witness_program)
- pkscript = CScript([OP_0, scripthash])
+ pkscript = script_to_p2wsh_script(witness_program)
return pkscript.hex()
def create_witness_tx(node, use_p2wsh, utxo, pubkey, encode_p2sh, amount):
diff --git a/test/functional/test_framework/wallet_util.py b/test/functional/test_framework/wallet_util.py
index b9c0fb6691..acbc040741 100755
--- a/test/functional/test_framework/wallet_util.py
+++ b/test/functional/test_framework/wallet_util.py
@@ -17,17 +17,15 @@ from test_framework.address import (
from test_framework.key import ECKey
from test_framework.script import (
CScript,
- OP_0,
OP_2,
OP_3,
OP_CHECKMULTISIG,
- OP_CHECKSIG,
- OP_DUP,
- OP_EQUAL,
- OP_EQUALVERIFY,
- OP_HASH160,
- hash160,
- sha256,
+)
+from test_framework.script_util import (
+ key_to_p2pkh_script,
+ key_to_p2wpkh_script,
+ script_to_p2sh_script,
+ script_to_p2wsh_script,
)
from test_framework.util import hex_str_to_bytes
@@ -57,15 +55,14 @@ def get_key(node):
Returns a named tuple of privkey, pubkey and all address and scripts."""
addr = node.getnewaddress()
pubkey = node.getaddressinfo(addr)['pubkey']
- pkh = hash160(hex_str_to_bytes(pubkey))
return Key(privkey=node.dumpprivkey(addr),
pubkey=pubkey,
- p2pkh_script=CScript([OP_DUP, OP_HASH160, pkh, OP_EQUALVERIFY, OP_CHECKSIG]).hex(),
+ p2pkh_script=key_to_p2pkh_script(pubkey).hex(),
p2pkh_addr=key_to_p2pkh(pubkey),
- p2wpkh_script=CScript([OP_0, pkh]).hex(),
+ p2wpkh_script=key_to_p2wpkh_script(pubkey).hex(),
p2wpkh_addr=key_to_p2wpkh(pubkey),
- p2sh_p2wpkh_script=CScript([OP_HASH160, hash160(CScript([OP_0, pkh])), OP_EQUAL]).hex(),
- p2sh_p2wpkh_redeem_script=CScript([OP_0, pkh]).hex(),
+ p2sh_p2wpkh_script=script_to_p2sh_script(key_to_p2wpkh_script(pubkey)).hex(),
+ p2sh_p2wpkh_redeem_script=key_to_p2wpkh_script(pubkey).hex(),
p2sh_p2wpkh_addr=key_to_p2sh_p2wpkh(pubkey))
def get_generate_key():
@@ -76,15 +73,14 @@ def get_generate_key():
eckey.generate()
privkey = bytes_to_wif(eckey.get_bytes())
pubkey = eckey.get_pubkey().get_bytes().hex()
- pkh = hash160(hex_str_to_bytes(pubkey))
return Key(privkey=privkey,
pubkey=pubkey,
- p2pkh_script=CScript([OP_DUP, OP_HASH160, pkh, OP_EQUALVERIFY, OP_CHECKSIG]).hex(),
+ p2pkh_script=key_to_p2pkh_script(pubkey).hex(),
p2pkh_addr=key_to_p2pkh(pubkey),
- p2wpkh_script=CScript([OP_0, pkh]).hex(),
+ p2wpkh_script=key_to_p2wpkh_script(pubkey).hex(),
p2wpkh_addr=key_to_p2wpkh(pubkey),
- p2sh_p2wpkh_script=CScript([OP_HASH160, hash160(CScript([OP_0, pkh])), OP_EQUAL]).hex(),
- p2sh_p2wpkh_redeem_script=CScript([OP_0, pkh]).hex(),
+ p2sh_p2wpkh_script=script_to_p2sh_script(key_to_p2wpkh_script(pubkey)).hex(),
+ p2sh_p2wpkh_redeem_script=key_to_p2wpkh_script(pubkey).hex(),
p2sh_p2wpkh_addr=key_to_p2sh_p2wpkh(pubkey))
def get_multisig(node):
@@ -98,15 +94,15 @@ def get_multisig(node):
addrs.append(addr['address'])
pubkeys.append(addr['pubkey'])
script_code = CScript([OP_2] + [hex_str_to_bytes(pubkey) for pubkey in pubkeys] + [OP_3, OP_CHECKMULTISIG])
- witness_script = CScript([OP_0, sha256(script_code)])
+ witness_script = script_to_p2wsh_script(script_code)
return Multisig(privkeys=[node.dumpprivkey(addr) for addr in addrs],
pubkeys=pubkeys,
- p2sh_script=CScript([OP_HASH160, hash160(script_code), OP_EQUAL]).hex(),
+ p2sh_script=script_to_p2sh_script(script_code).hex(),
p2sh_addr=script_to_p2sh(script_code),
redeem_script=script_code.hex(),
p2wsh_script=witness_script.hex(),
p2wsh_addr=script_to_p2wsh(script_code),
- p2sh_p2wsh_script=CScript([OP_HASH160, witness_script, OP_EQUAL]).hex(),
+ p2sh_p2wsh_script=script_to_p2sh_script(witness_script).hex(),
p2sh_p2wsh_addr=script_to_p2sh_p2wsh(script_code))
def test_address(node, address, **kwargs):
diff --git a/test/lint/lint-python.sh b/test/lint/lint-python.sh
index 51815963f6..c448fa6f9a 100755
--- a/test/lint/lint-python.sh
+++ b/test/lint/lint-python.sh
@@ -102,7 +102,7 @@ if ! PYTHONWARNINGS="ignore" flake8 --ignore=B,C,E,F,I,N,W --select=$(IFS=","; e
EXIT_CODE=1
fi
-if ! mypy --ignore-missing-imports $(git ls-files "test/functional/*.py" "contrib/devtools/*.py"); then
+if ! mypy --ignore-missing-imports --show-error-codes $(git ls-files "test/functional/*.py" "contrib/devtools/*.py"); then
EXIT_CODE=1
fi