diff --git a/cmake/utils/filter-lcov.py b/cmake/utils/filter-lcov.py index 6e0f54490..2eb8f189c 100755 --- a/cmake/utils/filter-lcov.py +++ b/cmake/utils/filter-lcov.py @@ -1,28 +1,31 @@ #!/usr/bin/env python3 +# Copyright (c) 2020 The Bitcoin developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. import argparse parser = argparse.ArgumentParser( description='Remove the coverage data from a tracefile for all files matching the pattern.') parser.add_argument('--pattern', '-p', action='append', help='the pattern of files to remove', required=True) parser.add_argument( 'tracefile', help='the tracefile to remove the coverage data from') parser.add_argument('outfile', help='filename for the output to be written to') args = parser.parse_args() tracefile = args.tracefile pattern = args.pattern outfile = args.outfile in_remove = False with open(tracefile, 'r', encoding="utf8") as f: with open(outfile, 'w', encoding="utf8") as wf: for line in f: for p in pattern: if line.startswith("SF:") and p in line: in_remove = True if not in_remove: wf.write(line) if line == 'end_of_record\n': in_remove = False diff --git a/contrib/devtools/circular-dependencies.py b/contrib/devtools/circular-dependencies.py index 2edee2cad..ce9bc62aa 100755 --- a/contrib/devtools/circular-dependencies.py +++ b/contrib/devtools/circular-dependencies.py @@ -1,93 +1,96 @@ #!/usr/bin/env python3 +# Copyright (c) 2018-2020 The Bitcoin developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. import re import sys MAPPING = { 'core_read.cpp': 'core_io.cpp', 'core_write.cpp': 'core_io.cpp', } # Directories with header-based modules, where the assumption that .cpp files # define functions and variables declared in corresponding .h files is # incorrect. HEADER_MODULE_PATHS = [ 'interfaces/' ] def module_name(path): if path in MAPPING: path = MAPPING[path] if any(path.startswith(dirpath) for dirpath in HEADER_MODULE_PATHS): return path if path.endswith(".h"): return path[:-2] if path.endswith(".c"): return path[:-2] if path.endswith(".cpp"): return path[:-4] return None files = dict() deps = dict() RE = re.compile("^#include <(.*)>") # Iterate over files, and create list of modules for arg in sys.argv[1:]: module = module_name(arg) if module is None: print("Ignoring file {} (does not constitute module)\n".format(arg)) else: files[arg] = module deps[module] = set() # Iterate again, and build list of direct dependencies for each module # TODO: implement support for multiple include directories for arg in sorted(files.keys()): module = files[arg] with open(arg, 'r', encoding="utf8") as f: for line in f: match = RE.match(line) if match: include = match.group(1) included_module = module_name(include) if included_module is not None and included_module in deps and included_module != module: deps[module].add(included_module) # Loop to find the shortest (remaining) circular dependency have_cycle = False while True: shortest_cycle = None for module in sorted(deps.keys()): # Build the transitive closure of dependencies of module closure = dict() for dep in deps[module]: closure[dep] = [] while True: old_size = len(closure) old_closure_keys = sorted(closure.keys()) for src in old_closure_keys: for dep in deps[src]: if dep not in closure: closure[dep] = closure[src] + [src] if len(closure) == old_size: break # If module is in its own transitive closure, it's a circular # dependency; check if it is the shortest if module in closure and (shortest_cycle is None or len( closure[module]) + 1 < len(shortest_cycle)): shortest_cycle = [module] + closure[module] if shortest_cycle is None: break # We have the shortest circular dependency; report it module = shortest_cycle[0] print("Circular dependency: {}".format( " -> ".join(shortest_cycle + [module]))) # And then break the dependency to avoid repeating in other cycles deps[shortest_cycle[-1]] = deps[shortest_cycle[-1]] - set([module]) have_cycle = True sys.exit(1 if have_cycle else 0) diff --git a/contrib/gitian-build.py b/contrib/gitian-build.py index fc86239e6..26c9411ce 100755 --- a/contrib/gitian-build.py +++ b/contrib/gitian-build.py @@ -1,312 +1,315 @@ #!/usr/bin/env python3 +# Copyright (c) 2019-2020 The Bitcoin developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. import argparse import multiprocessing import os import subprocess import sys def setup(): global args, workdir programs = ['ruby', 'git', 'apt-cacher-ng', 'make', 'wget'] if args.kvm: programs += ['python-vm-builder', 'qemu-kvm', 'qemu-utils'] elif args.docker: dockers = ['docker.io', 'docker-ce'] for i in dockers: return_code = subprocess.call( ['sudo', 'apt-get', 'install', '-qq', i]) if return_code == 0: break if return_code != 0: print('Cannot find any way to install docker', file=sys.stderr) exit(1) else: programs += ['lxc', 'debootstrap'] subprocess.check_call(['sudo', 'apt-get', 'install', '-qq'] + programs) if not os.path.isdir('gitian-builder'): subprocess.check_call( ['git', 'clone', 'https://github.com/devrandom/gitian-builder.git']) if not os.path.isdir('bitcoin-abc'): subprocess.check_call( ['git', 'clone', 'https://github.com/Bitcoin-ABC/bitcoin-abc.git']) os.chdir('gitian-builder') make_image_prog = ['bin/make-base-vm', '--distro', 'debian', '--suite', 'buster', '--arch', 'amd64'] if args.docker: make_image_prog += ['--docker'] elif not args.kvm: make_image_prog += ['--lxc'] subprocess.check_call(make_image_prog) os.chdir(workdir) if args.is_bionic and not args.kvm and not args.docker: subprocess.check_call( ['sudo', 'sed', '-i', 's/lxcbr0/br0/', '/etc/default/lxc-net']) print('Reboot is required') exit(0) def build(): global args, workdir base_output_dir = 'bitcoin-binaries/' + args.version os.makedirs(base_output_dir + '/src', exist_ok=True) print('\nBuilding Dependencies\n') os.chdir('gitian-builder') os.makedirs('inputs', exist_ok=True) subprocess.check_call(['make', '-C', '../bitcoin-abc/depends', 'download', 'SOURCES_PATH=' + os.getcwd() + '/cache/common']) output_dir_src = '../' + base_output_dir + '/src' if args.linux: print('\nCompiling ' + args.version + ' Linux') subprocess.check_call(['bin/gbuild', '-j', args.jobs, '-m', args.memory, '--commit', 'bitcoin=' + args.commit, '--url', 'bitcoin=' + args.url, '../bitcoin-abc/contrib/gitian-descriptors/gitian-linux.yml']) subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version + '-linux', '--destination', '../gitian.sigs/', '../bitcoin-abc/contrib/gitian-descriptors/gitian-linux.yml']) output_dir_linux = '../' + base_output_dir + '/linux' os.makedirs(output_dir_linux, exist_ok=True) subprocess.check_call( 'mv build/out/bitcoin-*.tar.gz ' + output_dir_linux, shell=True) subprocess.check_call( 'mv build/out/src/bitcoin-*.tar.gz ' + output_dir_src, shell=True) subprocess.check_call( 'mv result/bitcoin-*-linux-res.yml ' + output_dir_linux, shell=True) if args.windows: print('\nCompiling ' + args.version + ' Windows') subprocess.check_call(['bin/gbuild', '-j', args.jobs, '-m', args.memory, '--commit', 'bitcoin=' + args.commit, '--url', 'bitcoin=' + args.url, '../bitcoin-abc/contrib/gitian-descriptors/gitian-win.yml']) subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version + '-win-unsigned', '--destination', '../gitian.sigs/', '../bitcoin-abc/contrib/gitian-descriptors/gitian-win.yml']) output_dir_win = '../' + base_output_dir + '/win' os.makedirs(output_dir_win, exist_ok=True) subprocess.check_call( 'mv build/out/bitcoin-*-win-unsigned.tar.gz inputs/', shell=True) subprocess.check_call( 'mv build/out/bitcoin-*.zip build/out/bitcoin-*.exe ' + output_dir_win, shell=True) subprocess.check_call( 'mv build/out/src/bitcoin-*.tar.gz ' + output_dir_src, shell=True) subprocess.check_call( 'mv result/bitcoin-*-win-res.yml ' + output_dir_win, shell=True) if args.macos: print('\nCompiling ' + args.version + ' MacOS') subprocess.check_call(['bin/gbuild', '-j', args.jobs, '-m', args.memory, '--commit', 'bitcoin=' + args.commit, '--url', 'bitcoin=' + args.url, '../bitcoin-abc/contrib/gitian-descriptors/gitian-osx.yml']) subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version + '-osx-unsigned', '--destination', '../gitian.sigs/', '../bitcoin-abc/contrib/gitian-descriptors/gitian-osx.yml']) output_dir_osx = '../' + base_output_dir + '/osx' os.makedirs(output_dir_osx, exist_ok=True) subprocess.check_call( 'mv build/out/bitcoin-*-osx-unsigned.tar.gz inputs/', shell=True) subprocess.check_call( 'mv build/out/bitcoin-*.tar.gz build/out/bitcoin-*.dmg ' + output_dir_osx, shell=True) subprocess.check_call( 'mv build/out/src/bitcoin-*.tar.gz ' + output_dir_src, shell=True) subprocess.check_call( 'mv result/bitcoin-*-osx-res.yml ' + output_dir_osx, shell=True) os.chdir(workdir) if args.commit_files: print('\nCommitting ' + args.version + ' Unsigned Sigs\n') os.chdir('gitian.sigs') subprocess.check_call( ['git', 'add', args.version + '-linux/' + args.signer]) subprocess.check_call( ['git', 'add', args.version + '-win-unsigned/' + args.signer]) subprocess.check_call( ['git', 'add', args.version + '-osx-unsigned/' + args.signer]) subprocess.check_call( ['git', 'commit', '-m', 'Add ' + args.version + ' unsigned sigs for ' + args.signer]) os.chdir(workdir) def sign(): global args, workdir os.chdir('gitian-builder') if args.windows: print('\nSigning ' + args.version + ' Windows') subprocess.check_call('cp inputs/bitcoin-' + args.version + '-win-unsigned.tar.gz inputs/bitcoin-win-unsigned.tar.gz', shell=True) subprocess.check_call(['bin/gbuild', '-i', '--commit', 'signature=' + args.commit, '../bitcoin-abc/contrib/gitian-descriptors/gitian-win-signer.yml']) subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version + '-win-signed', '--destination', '../gitian.sigs/', '../bitcoin-abc/contrib/gitian-descriptors/gitian-win-signer.yml']) subprocess.check_call( 'mv build/out/bitcoin-*win64-setup.exe ../bitcoin-binaries/' + args.version, shell=True) if args.macos: print('\nSigning ' + args.version + ' MacOS') subprocess.check_call('cp inputs/bitcoin-' + args.version + '-osx-unsigned.tar.gz inputs/bitcoin-osx-unsigned.tar.gz', shell=True) subprocess.check_call(['bin/gbuild', '-i', '--commit', 'signature=' + args.commit, '../bitcoin-abc/contrib/gitian-descriptors/gitian-osx-signer.yml']) subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version + '-osx-signed', '--destination', '../gitian.sigs/', '../bitcoin-abc/contrib/gitian-descriptors/gitian-osx-signer.yml']) subprocess.check_call('mv build/out/bitcoin-osx-signed.dmg ../bitcoin-binaries/' + args.version + '/bitcoin-' + args.version + '-osx.dmg', shell=True) os.chdir(workdir) if args.commit_files: print('\nCommitting ' + args.version + ' Signed Sigs\n') os.chdir('gitian.sigs') subprocess.check_call( ['git', 'add', args.version + '-win-signed/' + args.signer]) subprocess.check_call( ['git', 'add', args.version + '-osx-signed/' + args.signer]) subprocess.check_call(['git', 'commit', '-a', '-m', 'Add ' + args.version + ' signed binary sigs for ' + args.signer]) os.chdir(workdir) def verify(): global args, workdir os.chdir('gitian-builder') print('\nVerifying v' + args.version + ' Linux\n') subprocess.check_call(['bin/gverify', '-v', '-d', '../gitian.sigs/', '-r', args.version + '-linux', '../bitcoin-abc/contrib/gitian-descriptors/gitian-linux.yml']) print('\nVerifying v' + args.version + ' Windows\n') subprocess.check_call(['bin/gverify', '-v', '-d', '../gitian.sigs/', '-r', args.version + '-win-unsigned', '../bitcoin-abc/contrib/gitian-descriptors/gitian-win.yml']) print('\nVerifying v' + args.version + ' MacOS\n') subprocess.check_call(['bin/gverify', '-v', '-d', '../gitian.sigs/', '-r', args.version + '-osx-unsigned', '../bitcoin-abc/contrib/gitian-descriptors/gitian-osx.yml']) print('\nVerifying v' + args.version + ' Signed Windows\n') subprocess.check_call(['bin/gverify', '-v', '-d', '../gitian.sigs/', '-r', args.version + '-win-signed', '../bitcoin-abc/contrib/gitian-descriptors/gitian-win-signer.yml']) print('\nVerifying v' + args.version + ' Signed MacOS\n') subprocess.check_call(['bin/gverify', '-v', '-d', '../gitian.sigs/', '-r', args.version + '-osx-signed', '../bitcoin-abc/contrib/gitian-descriptors/gitian-osx-signer.yml']) os.chdir(workdir) def main(): global args, workdir num_cpus = multiprocessing.cpu_count() parser = argparse.ArgumentParser(usage='%(prog)s [options] signer version') parser.add_argument('-c', '--commit', action='store_true', dest='commit', help='Indicate that the version argument is for a commit or branch') parser.add_argument('-p', '--pull', action='store_true', dest='pull', help='Indicate that the version argument is the number of a github repository pull request') parser.add_argument('-u', '--url', dest='url', default='https://github.com/Bitcoin-ABC/bitcoin-abc.git', help='Specify the URL of the repository. Default is %(default)s') parser.add_argument('-v', '--verify', action='store_true', dest='verify', help='Verify the Gitian build') parser.add_argument('-b', '--build', action='store_true', dest='build', help='Do a Gitian build') parser.add_argument('-s', '--sign', action='store_true', dest='sign', help='Make signed binaries for Windows and MacOS') parser.add_argument('-B', '--buildsign', action='store_true', dest='buildsign', help='Build both signed and unsigned binaries') parser.add_argument('-o', '--os', dest='os', default='lwm', help='Specify which Operating Systems the build is for. Default is %(default)s. l for Linux, w for Windows, m for MacOS') parser.add_argument('-j', '--jobs', dest='jobs', default=str(num_cpus), help='Number of processes to use. Default %(default)s') parser.add_argument('-m', '--memory', dest='memory', default='3500', help='Memory to allocate in MiB. Default %(default)s') parser.add_argument('-k', '--kvm', action='store_true', dest='kvm', help='Use KVM instead of LXC') parser.add_argument('-d', '--docker', action='store_true', dest='docker', help='Use Docker instead of LXC') parser.add_argument('-S', '--setup', action='store_true', dest='setup', help='Set up the Gitian building environment. Uses LXC. If you want to use KVM, use the --kvm option. Only works on Debian-based systems (Ubuntu, Debian)') parser.add_argument('-D', '--detach-sign', action='store_true', dest='detach_sign', help='Create the assert file for detached signing. Will not commit anything.') parser.add_argument('-n', '--no-commit', action='store_false', dest='commit_files', help='Do not commit anything to git') parser.add_argument( 'signer', help='GPG signer to sign each build assert file') parser.add_argument( 'version', help='Version number, commit, or branch to build. If building a commit or branch, the -c option must be specified') args = parser.parse_args() workdir = os.getcwd() args.linux = 'l' in args.os args.windows = 'w' in args.os args.macos = 'm' in args.os args.is_bionic = b'bionic' in subprocess.check_output( ['lsb_release', '-cs']) if args.buildsign: args.build = True args.sign = True if args.kvm and args.docker: raise Exception('Error: cannot have both kvm and docker') args.sign_prog = 'true' if args.detach_sign else 'gpg --detach-sign' # Set environment variable USE_LXC or USE_DOCKER, let gitian-builder know # that we use lxc or docker if args.docker: os.environ['USE_DOCKER'] = '1' elif not args.kvm: os.environ['USE_LXC'] = '1' if 'GITIAN_HOST_IP' not in os.environ.keys(): os.environ['GITIAN_HOST_IP'] = '10.0.3.1' if 'LXC_GUEST_IP' not in os.environ.keys(): os.environ['LXC_GUEST_IP'] = '10.0.3.5' # Disable for MacOS if no SDK found if args.macos and not os.path.isfile( 'gitian-builder/inputs/Xcode-11.3.1-11C505-extracted-SDK-with-libcxx-headers.tar.gz'): print('Cannot build for MacOS, SDK does not exist. Will build for other OSes') args.macos = False script_name = os.path.basename(sys.argv[0]) # Signer and version shouldn't be empty if args.signer == '': print(script_name + ': Missing signer.') print('Try ' + script_name + ' --help for more information') exit(1) if args.version == '': print(script_name + ': Missing version.') print('Try ' + script_name + ' --help for more information') exit(1) # Add leading 'v' for tags if args.commit and args.pull: raise Exception('Cannot have both commit and pull') args.commit = ('' if args.commit else 'v') + args.version if args.setup: setup() os.chdir('bitcoin-abc') if args.pull: subprocess.check_call( ['git', 'fetch', args.url, 'refs/pull/' + args.version + '/merge']) os.chdir('../gitian-builder/inputs/bitcoin') subprocess.check_call( ['git', 'fetch', args.url, 'refs/pull/' + args.version + '/merge']) args.commit = subprocess.check_output( ['git', 'show', '-s', '--format=%H', 'FETCH_HEAD'], universal_newlines=True, encoding='utf8').strip() args.version = 'pull-' + args.version print(args.commit) subprocess.check_call(['git', 'fetch']) subprocess.check_call(['git', 'checkout', args.commit]) os.chdir(workdir) if args.build: build() if args.sign: sign() if args.verify: verify() if __name__ == '__main__': main() diff --git a/doc/man/gen-manpages.sh b/doc/man/gen-manpages.sh index 6e3f813a5..618c2fa9e 100755 --- a/doc/man/gen-manpages.sh +++ b/doc/man/gen-manpages.sh @@ -1,60 +1,63 @@ #!/usr/bin/env bash +# Copyright (c) 2020 The Bitcoin developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. export LC_ALL=C set -euxo pipefail usage() { cat << EOF Usage: $0 bitcoind binary manpage bitcoind: path to bitcoind executable binary: path to the binary to generate the man pages from manpage: output path for the man page EOF } if [ $# -ne 3 ] then usage exit 1 fi if ! command -v help2man then echo "help2man is required to run $0, please install it" exit 2 fi BITCOIND="$1" BIN="$2" MANPAGE="$3" if [ ! -x "${BITCOIND}" ] then echo "${BITCOIND} not found or not executable." exit 4 fi if [ ! -x "${BIN}" ] then echo "${BIN} not found or not executable." exit 5 fi mkdir -p "$(dirname ${MANPAGE})" # The autodetected version git tag can screw up manpage output a little bit read -r -a VERSION <<< "$(${BITCOIND} --version | awk -F'[ -]' 'NR == 1 { print $4, $5 }')" # Create a footer file with copyright content. # This gets autodetected fine for bitcoind if --version-string is not set, # but has different outcomes for bitcoin-qt and bitcoin-cli. FOOTER="$(basename ${BIN})_footer.h2m" cleanup() { rm -f "${FOOTER}" } trap "cleanup" EXIT echo "[COPYRIGHT]" > "${FOOTER}" "${BITCOIND}" --version | sed -n '1!p' >> "${FOOTER}" help2man -N --version-string="${VERSION[0]}" --include="${FOOTER}" -o "${MANPAGE}" "${BIN}" sed -i "s/\\\-${VERSION[1]}//g" "${MANPAGE}" diff --git a/src/crypto/sha256_avx2.cpp b/src/crypto/sha256_avx2.cpp index 61a3d7ea3..01f990256 100644 --- a/src/crypto/sha256_avx2.cpp +++ b/src/crypto/sha256_avx2.cpp @@ -1,453 +1,457 @@ +// Copyright (c) 2017-2019 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + #ifdef ENABLE_AVX2 #include #include #include namespace sha256d64_avx2 { namespace { __m256i inline K(uint32_t x) { return _mm256_set1_epi32(x); } __m256i inline Add(__m256i x, __m256i y) { return _mm256_add_epi32(x, y); } __m256i inline Add(__m256i x, __m256i y, __m256i z) { return Add(Add(x, y), z); } __m256i inline Add(__m256i x, __m256i y, __m256i z, __m256i w) { return Add(Add(x, y), Add(z, w)); } __m256i inline Add(__m256i x, __m256i y, __m256i z, __m256i w, __m256i v) { return Add(Add(x, y, z), Add(w, v)); } __m256i inline Inc(__m256i &x, __m256i y) { x = Add(x, y); return x; } __m256i inline Inc(__m256i &x, __m256i y, __m256i z) { x = Add(x, y, z); return x; } __m256i inline Inc(__m256i &x, __m256i y, __m256i z, __m256i w) { x = Add(x, y, z, w); return x; } __m256i inline Xor(__m256i x, __m256i y) { return _mm256_xor_si256(x, y); } __m256i inline Xor(__m256i x, __m256i y, __m256i z) { return Xor(Xor(x, y), z); } __m256i inline Or(__m256i x, __m256i y) { return _mm256_or_si256(x, y); } __m256i inline And(__m256i x, __m256i y) { return _mm256_and_si256(x, y); } __m256i inline ShR(__m256i x, int n) { return _mm256_srli_epi32(x, n); } __m256i inline ShL(__m256i x, int n) { return _mm256_slli_epi32(x, n); } __m256i inline Ch(__m256i x, __m256i y, __m256i z) { return Xor(z, And(x, Xor(y, z))); } __m256i inline Maj(__m256i x, __m256i y, __m256i z) { return Or(And(x, y), And(z, Or(x, y))); } __m256i inline Sigma0(__m256i x) { return Xor(Or(ShR(x, 2), ShL(x, 30)), Or(ShR(x, 13), ShL(x, 19)), Or(ShR(x, 22), ShL(x, 10))); } __m256i inline Sigma1(__m256i x) { return Xor(Or(ShR(x, 6), ShL(x, 26)), Or(ShR(x, 11), ShL(x, 21)), Or(ShR(x, 25), ShL(x, 7))); } __m256i inline sigma0(__m256i x) { return Xor(Or(ShR(x, 7), ShL(x, 25)), Or(ShR(x, 18), ShL(x, 14)), ShR(x, 3)); } __m256i inline sigma1(__m256i x) { return Xor(Or(ShR(x, 17), ShL(x, 15)), Or(ShR(x, 19), ShL(x, 13)), ShR(x, 10)); } /** One round of SHA-256. */ inline void __attribute__((always_inline)) Round(__m256i a, __m256i b, __m256i c, __m256i &d, __m256i e, __m256i f, __m256i g, __m256i &h, __m256i k) { __m256i t1 = Add(h, Sigma1(e), Ch(e, f, g), k); __m256i t2 = Add(Sigma0(a), Maj(a, b, c)); d = Add(d, t1); h = Add(t1, t2); } __m256i inline Read8(const uint8_t *chunk, int offset) { __m256i ret = _mm256_set_epi32( ReadLE32(chunk + 0 + offset), ReadLE32(chunk + 64 + offset), ReadLE32(chunk + 128 + offset), ReadLE32(chunk + 192 + offset), ReadLE32(chunk + 256 + offset), ReadLE32(chunk + 320 + offset), ReadLE32(chunk + 384 + offset), ReadLE32(chunk + 448 + offset)); return _mm256_shuffle_epi8( ret, _mm256_set_epi32(0x0C0D0E0FUL, 0x08090A0BUL, 0x04050607UL, 0x00010203UL, 0x0C0D0E0FUL, 0x08090A0BUL, 0x04050607UL, 0x00010203UL)); } inline void Write8(uint8_t *out, int offset, __m256i v) { v = _mm256_shuffle_epi8( v, _mm256_set_epi32(0x0C0D0E0FUL, 0x08090A0BUL, 0x04050607UL, 0x00010203UL, 0x0C0D0E0FUL, 0x08090A0BUL, 0x04050607UL, 0x00010203UL)); WriteLE32(out + 0 + offset, _mm256_extract_epi32(v, 7)); WriteLE32(out + 32 + offset, _mm256_extract_epi32(v, 6)); WriteLE32(out + 64 + offset, _mm256_extract_epi32(v, 5)); WriteLE32(out + 96 + offset, _mm256_extract_epi32(v, 4)); WriteLE32(out + 128 + offset, _mm256_extract_epi32(v, 3)); WriteLE32(out + 160 + offset, _mm256_extract_epi32(v, 2)); WriteLE32(out + 192 + offset, _mm256_extract_epi32(v, 1)); WriteLE32(out + 224 + offset, _mm256_extract_epi32(v, 0)); } } // namespace void Transform_8way(uint8_t *out, const uint8_t *in) { // Transform 1 __m256i a = K(0x6a09e667ul); __m256i b = K(0xbb67ae85ul); __m256i c = K(0x3c6ef372ul); __m256i d = K(0xa54ff53aul); __m256i e = K(0x510e527ful); __m256i f = K(0x9b05688cul); __m256i g = K(0x1f83d9abul); __m256i h = K(0x5be0cd19ul); __m256i w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; Round(a, b, c, d, e, f, g, h, Add(K(0x428a2f98ul), w0 = Read8(in, 0))); Round(h, a, b, c, d, e, f, g, Add(K(0x71374491ul), w1 = Read8(in, 4))); Round(g, h, a, b, c, d, e, f, Add(K(0xb5c0fbcful), w2 = Read8(in, 8))); Round(f, g, h, a, b, c, d, e, Add(K(0xe9b5dba5ul), w3 = Read8(in, 12))); Round(e, f, g, h, a, b, c, d, Add(K(0x3956c25bul), w4 = Read8(in, 16))); Round(d, e, f, g, h, a, b, c, Add(K(0x59f111f1ul), w5 = Read8(in, 20))); Round(c, d, e, f, g, h, a, b, Add(K(0x923f82a4ul), w6 = Read8(in, 24))); Round(b, c, d, e, f, g, h, a, Add(K(0xab1c5ed5ul), w7 = Read8(in, 28))); Round(a, b, c, d, e, f, g, h, Add(K(0xd807aa98ul), w8 = Read8(in, 32))); Round(h, a, b, c, d, e, f, g, Add(K(0x12835b01ul), w9 = Read8(in, 36))); Round(g, h, a, b, c, d, e, f, Add(K(0x243185beul), w10 = Read8(in, 40))); Round(f, g, h, a, b, c, d, e, Add(K(0x550c7dc3ul), w11 = Read8(in, 44))); Round(e, f, g, h, a, b, c, d, Add(K(0x72be5d74ul), w12 = Read8(in, 48))); Round(d, e, f, g, h, a, b, c, Add(K(0x80deb1feul), w13 = Read8(in, 52))); Round(c, d, e, f, g, h, a, b, Add(K(0x9bdc06a7ul), w14 = Read8(in, 56))); Round(b, c, d, e, f, g, h, a, Add(K(0xc19bf174ul), w15 = Read8(in, 60))); Round(a, b, c, d, e, f, g, h, Add(K(0xe49b69c1ul), Inc(w0, sigma1(w14), w9, sigma0(w1)))); Round(h, a, b, c, d, e, f, g, Add(K(0xefbe4786ul), Inc(w1, sigma1(w15), w10, sigma0(w2)))); Round(g, h, a, b, c, d, e, f, Add(K(0x0fc19dc6ul), Inc(w2, sigma1(w0), w11, sigma0(w3)))); Round(f, g, h, a, b, c, d, e, Add(K(0x240ca1ccul), Inc(w3, sigma1(w1), w12, sigma0(w4)))); Round(e, f, g, h, a, b, c, d, Add(K(0x2de92c6ful), Inc(w4, sigma1(w2), w13, sigma0(w5)))); Round(d, e, f, g, h, a, b, c, Add(K(0x4a7484aaul), Inc(w5, sigma1(w3), w14, sigma0(w6)))); Round(c, d, e, f, g, h, a, b, Add(K(0x5cb0a9dcul), Inc(w6, sigma1(w4), w15, sigma0(w7)))); Round(b, c, d, e, f, g, h, a, Add(K(0x76f988daul), Inc(w7, sigma1(w5), w0, sigma0(w8)))); Round(a, b, c, d, e, f, g, h, Add(K(0x983e5152ul), Inc(w8, sigma1(w6), w1, sigma0(w9)))); Round(h, a, b, c, d, e, f, g, Add(K(0xa831c66dul), Inc(w9, sigma1(w7), w2, sigma0(w10)))); Round(g, h, a, b, c, d, e, f, Add(K(0xb00327c8ul), Inc(w10, sigma1(w8), w3, sigma0(w11)))); Round(f, g, h, a, b, c, d, e, Add(K(0xbf597fc7ul), Inc(w11, sigma1(w9), w4, sigma0(w12)))); Round(e, f, g, h, a, b, c, d, Add(K(0xc6e00bf3ul), Inc(w12, sigma1(w10), w5, sigma0(w13)))); Round(d, e, f, g, h, a, b, c, Add(K(0xd5a79147ul), Inc(w13, sigma1(w11), w6, sigma0(w14)))); Round(c, d, e, f, g, h, a, b, Add(K(0x06ca6351ul), Inc(w14, sigma1(w12), w7, sigma0(w15)))); Round(b, c, d, e, f, g, h, a, Add(K(0x14292967ul), Inc(w15, sigma1(w13), w8, sigma0(w0)))); Round(a, b, c, d, e, f, g, h, Add(K(0x27b70a85ul), Inc(w0, sigma1(w14), w9, sigma0(w1)))); Round(h, a, b, c, d, e, f, g, Add(K(0x2e1b2138ul), Inc(w1, sigma1(w15), w10, sigma0(w2)))); Round(g, h, a, b, c, d, e, f, Add(K(0x4d2c6dfcul), Inc(w2, sigma1(w0), w11, sigma0(w3)))); Round(f, g, h, a, b, c, d, e, Add(K(0x53380d13ul), Inc(w3, sigma1(w1), w12, sigma0(w4)))); Round(e, f, g, h, a, b, c, d, Add(K(0x650a7354ul), Inc(w4, sigma1(w2), w13, sigma0(w5)))); Round(d, e, f, g, h, a, b, c, Add(K(0x766a0abbul), Inc(w5, sigma1(w3), w14, sigma0(w6)))); Round(c, d, e, f, g, h, a, b, Add(K(0x81c2c92eul), Inc(w6, sigma1(w4), w15, sigma0(w7)))); Round(b, c, d, e, f, g, h, a, Add(K(0x92722c85ul), Inc(w7, sigma1(w5), w0, sigma0(w8)))); Round(a, b, c, d, e, f, g, h, Add(K(0xa2bfe8a1ul), Inc(w8, sigma1(w6), w1, sigma0(w9)))); Round(h, a, b, c, d, e, f, g, Add(K(0xa81a664bul), Inc(w9, sigma1(w7), w2, sigma0(w10)))); Round(g, h, a, b, c, d, e, f, Add(K(0xc24b8b70ul), Inc(w10, sigma1(w8), w3, sigma0(w11)))); Round(f, g, h, a, b, c, d, e, Add(K(0xc76c51a3ul), Inc(w11, sigma1(w9), w4, sigma0(w12)))); Round(e, f, g, h, a, b, c, d, Add(K(0xd192e819ul), Inc(w12, sigma1(w10), w5, sigma0(w13)))); Round(d, e, f, g, h, a, b, c, Add(K(0xd6990624ul), Inc(w13, sigma1(w11), w6, sigma0(w14)))); Round(c, d, e, f, g, h, a, b, Add(K(0xf40e3585ul), Inc(w14, sigma1(w12), w7, sigma0(w15)))); Round(b, c, d, e, f, g, h, a, Add(K(0x106aa070ul), Inc(w15, sigma1(w13), w8, sigma0(w0)))); Round(a, b, c, d, e, f, g, h, Add(K(0x19a4c116ul), Inc(w0, sigma1(w14), w9, sigma0(w1)))); Round(h, a, b, c, d, e, f, g, Add(K(0x1e376c08ul), Inc(w1, sigma1(w15), w10, sigma0(w2)))); Round(g, h, a, b, c, d, e, f, Add(K(0x2748774cul), Inc(w2, sigma1(w0), w11, sigma0(w3)))); Round(f, g, h, a, b, c, d, e, Add(K(0x34b0bcb5ul), Inc(w3, sigma1(w1), w12, sigma0(w4)))); Round(e, f, g, h, a, b, c, d, Add(K(0x391c0cb3ul), Inc(w4, sigma1(w2), w13, sigma0(w5)))); Round(d, e, f, g, h, a, b, c, Add(K(0x4ed8aa4aul), Inc(w5, sigma1(w3), w14, sigma0(w6)))); Round(c, d, e, f, g, h, a, b, Add(K(0x5b9cca4ful), Inc(w6, sigma1(w4), w15, sigma0(w7)))); Round(b, c, d, e, f, g, h, a, Add(K(0x682e6ff3ul), Inc(w7, sigma1(w5), w0, sigma0(w8)))); Round(a, b, c, d, e, f, g, h, Add(K(0x748f82eeul), Inc(w8, sigma1(w6), w1, sigma0(w9)))); Round(h, a, b, c, d, e, f, g, Add(K(0x78a5636ful), Inc(w9, sigma1(w7), w2, sigma0(w10)))); Round(g, h, a, b, c, d, e, f, Add(K(0x84c87814ul), Inc(w10, sigma1(w8), w3, sigma0(w11)))); Round(f, g, h, a, b, c, d, e, Add(K(0x8cc70208ul), Inc(w11, sigma1(w9), w4, sigma0(w12)))); Round(e, f, g, h, a, b, c, d, Add(K(0x90befffaul), Inc(w12, sigma1(w10), w5, sigma0(w13)))); Round(d, e, f, g, h, a, b, c, Add(K(0xa4506cebul), Inc(w13, sigma1(w11), w6, sigma0(w14)))); Round(c, d, e, f, g, h, a, b, Add(K(0xbef9a3f7ul), Inc(w14, sigma1(w12), w7, sigma0(w15)))); Round(b, c, d, e, f, g, h, a, Add(K(0xc67178f2ul), Inc(w15, sigma1(w13), w8, sigma0(w0)))); a = Add(a, K(0x6a09e667ul)); b = Add(b, K(0xbb67ae85ul)); c = Add(c, K(0x3c6ef372ul)); d = Add(d, K(0xa54ff53aul)); e = Add(e, K(0x510e527ful)); f = Add(f, K(0x9b05688cul)); g = Add(g, K(0x1f83d9abul)); h = Add(h, K(0x5be0cd19ul)); __m256i t0 = a, t1 = b, t2 = c, t3 = d, t4 = e, t5 = f, t6 = g, t7 = h; // Transform 2 Round(a, b, c, d, e, f, g, h, K(0xc28a2f98ul)); Round(h, a, b, c, d, e, f, g, K(0x71374491ul)); Round(g, h, a, b, c, d, e, f, K(0xb5c0fbcful)); Round(f, g, h, a, b, c, d, e, K(0xe9b5dba5ul)); Round(e, f, g, h, a, b, c, d, K(0x3956c25bul)); Round(d, e, f, g, h, a, b, c, K(0x59f111f1ul)); Round(c, d, e, f, g, h, a, b, K(0x923f82a4ul)); Round(b, c, d, e, f, g, h, a, K(0xab1c5ed5ul)); Round(a, b, c, d, e, f, g, h, K(0xd807aa98ul)); Round(h, a, b, c, d, e, f, g, K(0x12835b01ul)); Round(g, h, a, b, c, d, e, f, K(0x243185beul)); Round(f, g, h, a, b, c, d, e, K(0x550c7dc3ul)); Round(e, f, g, h, a, b, c, d, K(0x72be5d74ul)); Round(d, e, f, g, h, a, b, c, K(0x80deb1feul)); Round(c, d, e, f, g, h, a, b, K(0x9bdc06a7ul)); Round(b, c, d, e, f, g, h, a, K(0xc19bf374ul)); Round(a, b, c, d, e, f, g, h, K(0x649b69c1ul)); Round(h, a, b, c, d, e, f, g, K(0xf0fe4786ul)); Round(g, h, a, b, c, d, e, f, K(0x0fe1edc6ul)); Round(f, g, h, a, b, c, d, e, K(0x240cf254ul)); Round(e, f, g, h, a, b, c, d, K(0x4fe9346ful)); Round(d, e, f, g, h, a, b, c, K(0x6cc984beul)); Round(c, d, e, f, g, h, a, b, K(0x61b9411eul)); Round(b, c, d, e, f, g, h, a, K(0x16f988faul)); Round(a, b, c, d, e, f, g, h, K(0xf2c65152ul)); Round(h, a, b, c, d, e, f, g, K(0xa88e5a6dul)); Round(g, h, a, b, c, d, e, f, K(0xb019fc65ul)); Round(f, g, h, a, b, c, d, e, K(0xb9d99ec7ul)); Round(e, f, g, h, a, b, c, d, K(0x9a1231c3ul)); Round(d, e, f, g, h, a, b, c, K(0xe70eeaa0ul)); Round(c, d, e, f, g, h, a, b, K(0xfdb1232bul)); Round(b, c, d, e, f, g, h, a, K(0xc7353eb0ul)); Round(a, b, c, d, e, f, g, h, K(0x3069bad5ul)); Round(h, a, b, c, d, e, f, g, K(0xcb976d5ful)); Round(g, h, a, b, c, d, e, f, K(0x5a0f118ful)); Round(f, g, h, a, b, c, d, e, K(0xdc1eeefdul)); Round(e, f, g, h, a, b, c, d, K(0x0a35b689ul)); Round(d, e, f, g, h, a, b, c, K(0xde0b7a04ul)); Round(c, d, e, f, g, h, a, b, K(0x58f4ca9dul)); Round(b, c, d, e, f, g, h, a, K(0xe15d5b16ul)); Round(a, b, c, d, e, f, g, h, K(0x007f3e86ul)); Round(h, a, b, c, d, e, f, g, K(0x37088980ul)); Round(g, h, a, b, c, d, e, f, K(0xa507ea32ul)); Round(f, g, h, a, b, c, d, e, K(0x6fab9537ul)); Round(e, f, g, h, a, b, c, d, K(0x17406110ul)); Round(d, e, f, g, h, a, b, c, K(0x0d8cd6f1ul)); Round(c, d, e, f, g, h, a, b, K(0xcdaa3b6dul)); Round(b, c, d, e, f, g, h, a, K(0xc0bbbe37ul)); Round(a, b, c, d, e, f, g, h, K(0x83613bdaul)); Round(h, a, b, c, d, e, f, g, K(0xdb48a363ul)); Round(g, h, a, b, c, d, e, f, K(0x0b02e931ul)); Round(f, g, h, a, b, c, d, e, K(0x6fd15ca7ul)); Round(e, f, g, h, a, b, c, d, K(0x521afacaul)); Round(d, e, f, g, h, a, b, c, K(0x31338431ul)); Round(c, d, e, f, g, h, a, b, K(0x6ed41a95ul)); Round(b, c, d, e, f, g, h, a, K(0x6d437890ul)); Round(a, b, c, d, e, f, g, h, K(0xc39c91f2ul)); Round(h, a, b, c, d, e, f, g, K(0x9eccabbdul)); Round(g, h, a, b, c, d, e, f, K(0xb5c9a0e6ul)); Round(f, g, h, a, b, c, d, e, K(0x532fb63cul)); Round(e, f, g, h, a, b, c, d, K(0xd2c741c6ul)); Round(d, e, f, g, h, a, b, c, K(0x07237ea3ul)); Round(c, d, e, f, g, h, a, b, K(0xa4954b68ul)); Round(b, c, d, e, f, g, h, a, K(0x4c191d76ul)); w0 = Add(t0, a); w1 = Add(t1, b); w2 = Add(t2, c); w3 = Add(t3, d); w4 = Add(t4, e); w5 = Add(t5, f); w6 = Add(t6, g); w7 = Add(t7, h); // Transform 3 a = K(0x6a09e667ul); b = K(0xbb67ae85ul); c = K(0x3c6ef372ul); d = K(0xa54ff53aul); e = K(0x510e527ful); f = K(0x9b05688cul); g = K(0x1f83d9abul); h = K(0x5be0cd19ul); Round(a, b, c, d, e, f, g, h, Add(K(0x428a2f98ul), w0)); Round(h, a, b, c, d, e, f, g, Add(K(0x71374491ul), w1)); Round(g, h, a, b, c, d, e, f, Add(K(0xb5c0fbcful), w2)); Round(f, g, h, a, b, c, d, e, Add(K(0xe9b5dba5ul), w3)); Round(e, f, g, h, a, b, c, d, Add(K(0x3956c25bul), w4)); Round(d, e, f, g, h, a, b, c, Add(K(0x59f111f1ul), w5)); Round(c, d, e, f, g, h, a, b, Add(K(0x923f82a4ul), w6)); Round(b, c, d, e, f, g, h, a, Add(K(0xab1c5ed5ul), w7)); Round(a, b, c, d, e, f, g, h, K(0x5807aa98ul)); Round(h, a, b, c, d, e, f, g, K(0x12835b01ul)); Round(g, h, a, b, c, d, e, f, K(0x243185beul)); Round(f, g, h, a, b, c, d, e, K(0x550c7dc3ul)); Round(e, f, g, h, a, b, c, d, K(0x72be5d74ul)); Round(d, e, f, g, h, a, b, c, K(0x80deb1feul)); Round(c, d, e, f, g, h, a, b, K(0x9bdc06a7ul)); Round(b, c, d, e, f, g, h, a, K(0xc19bf274ul)); Round(a, b, c, d, e, f, g, h, Add(K(0xe49b69c1ul), Inc(w0, sigma0(w1)))); Round(h, a, b, c, d, e, f, g, Add(K(0xefbe4786ul), Inc(w1, K(0xa00000ul), sigma0(w2)))); Round(g, h, a, b, c, d, e, f, Add(K(0x0fc19dc6ul), Inc(w2, sigma1(w0), sigma0(w3)))); Round(f, g, h, a, b, c, d, e, Add(K(0x240ca1ccul), Inc(w3, sigma1(w1), sigma0(w4)))); Round(e, f, g, h, a, b, c, d, Add(K(0x2de92c6ful), Inc(w4, sigma1(w2), sigma0(w5)))); Round(d, e, f, g, h, a, b, c, Add(K(0x4a7484aaul), Inc(w5, sigma1(w3), sigma0(w6)))); Round(c, d, e, f, g, h, a, b, Add(K(0x5cb0a9dcul), Inc(w6, sigma1(w4), K(0x100ul), sigma0(w7)))); Round(b, c, d, e, f, g, h, a, Add(K(0x76f988daul), Inc(w7, sigma1(w5), w0, K(0x11002000ul)))); Round(a, b, c, d, e, f, g, h, Add(K(0x983e5152ul), w8 = Add(K(0x80000000ul), sigma1(w6), w1))); Round(h, a, b, c, d, e, f, g, Add(K(0xa831c66dul), w9 = Add(sigma1(w7), w2))); Round(g, h, a, b, c, d, e, f, Add(K(0xb00327c8ul), w10 = Add(sigma1(w8), w3))); Round(f, g, h, a, b, c, d, e, Add(K(0xbf597fc7ul), w11 = Add(sigma1(w9), w4))); Round(e, f, g, h, a, b, c, d, Add(K(0xc6e00bf3ul), w12 = Add(sigma1(w10), w5))); Round(d, e, f, g, h, a, b, c, Add(K(0xd5a79147ul), w13 = Add(sigma1(w11), w6))); Round(c, d, e, f, g, h, a, b, Add(K(0x06ca6351ul), w14 = Add(sigma1(w12), w7, K(0x400022ul)))); Round(b, c, d, e, f, g, h, a, Add(K(0x14292967ul), w15 = Add(K(0x100ul), sigma1(w13), w8, sigma0(w0)))); Round(a, b, c, d, e, f, g, h, Add(K(0x27b70a85ul), Inc(w0, sigma1(w14), w9, sigma0(w1)))); Round(h, a, b, c, d, e, f, g, Add(K(0x2e1b2138ul), Inc(w1, sigma1(w15), w10, sigma0(w2)))); Round(g, h, a, b, c, d, e, f, Add(K(0x4d2c6dfcul), Inc(w2, sigma1(w0), w11, sigma0(w3)))); Round(f, g, h, a, b, c, d, e, Add(K(0x53380d13ul), Inc(w3, sigma1(w1), w12, sigma0(w4)))); Round(e, f, g, h, a, b, c, d, Add(K(0x650a7354ul), Inc(w4, sigma1(w2), w13, sigma0(w5)))); Round(d, e, f, g, h, a, b, c, Add(K(0x766a0abbul), Inc(w5, sigma1(w3), w14, sigma0(w6)))); Round(c, d, e, f, g, h, a, b, Add(K(0x81c2c92eul), Inc(w6, sigma1(w4), w15, sigma0(w7)))); Round(b, c, d, e, f, g, h, a, Add(K(0x92722c85ul), Inc(w7, sigma1(w5), w0, sigma0(w8)))); Round(a, b, c, d, e, f, g, h, Add(K(0xa2bfe8a1ul), Inc(w8, sigma1(w6), w1, sigma0(w9)))); Round(h, a, b, c, d, e, f, g, Add(K(0xa81a664bul), Inc(w9, sigma1(w7), w2, sigma0(w10)))); Round(g, h, a, b, c, d, e, f, Add(K(0xc24b8b70ul), Inc(w10, sigma1(w8), w3, sigma0(w11)))); Round(f, g, h, a, b, c, d, e, Add(K(0xc76c51a3ul), Inc(w11, sigma1(w9), w4, sigma0(w12)))); Round(e, f, g, h, a, b, c, d, Add(K(0xd192e819ul), Inc(w12, sigma1(w10), w5, sigma0(w13)))); Round(d, e, f, g, h, a, b, c, Add(K(0xd6990624ul), Inc(w13, sigma1(w11), w6, sigma0(w14)))); Round(c, d, e, f, g, h, a, b, Add(K(0xf40e3585ul), Inc(w14, sigma1(w12), w7, sigma0(w15)))); Round(b, c, d, e, f, g, h, a, Add(K(0x106aa070ul), Inc(w15, sigma1(w13), w8, sigma0(w0)))); Round(a, b, c, d, e, f, g, h, Add(K(0x19a4c116ul), Inc(w0, sigma1(w14), w9, sigma0(w1)))); Round(h, a, b, c, d, e, f, g, Add(K(0x1e376c08ul), Inc(w1, sigma1(w15), w10, sigma0(w2)))); Round(g, h, a, b, c, d, e, f, Add(K(0x2748774cul), Inc(w2, sigma1(w0), w11, sigma0(w3)))); Round(f, g, h, a, b, c, d, e, Add(K(0x34b0bcb5ul), Inc(w3, sigma1(w1), w12, sigma0(w4)))); Round(e, f, g, h, a, b, c, d, Add(K(0x391c0cb3ul), Inc(w4, sigma1(w2), w13, sigma0(w5)))); Round(d, e, f, g, h, a, b, c, Add(K(0x4ed8aa4aul), Inc(w5, sigma1(w3), w14, sigma0(w6)))); Round(c, d, e, f, g, h, a, b, Add(K(0x5b9cca4ful), Inc(w6, sigma1(w4), w15, sigma0(w7)))); Round(b, c, d, e, f, g, h, a, Add(K(0x682e6ff3ul), Inc(w7, sigma1(w5), w0, sigma0(w8)))); Round(a, b, c, d, e, f, g, h, Add(K(0x748f82eeul), Inc(w8, sigma1(w6), w1, sigma0(w9)))); Round(h, a, b, c, d, e, f, g, Add(K(0x78a5636ful), Inc(w9, sigma1(w7), w2, sigma0(w10)))); Round(g, h, a, b, c, d, e, f, Add(K(0x84c87814ul), Inc(w10, sigma1(w8), w3, sigma0(w11)))); Round(f, g, h, a, b, c, d, e, Add(K(0x8cc70208ul), Inc(w11, sigma1(w9), w4, sigma0(w12)))); Round(e, f, g, h, a, b, c, d, Add(K(0x90befffaul), Inc(w12, sigma1(w10), w5, sigma0(w13)))); Round(d, e, f, g, h, a, b, c, Add(K(0xa4506cebul), Inc(w13, sigma1(w11), w6, sigma0(w14)))); Round(c, d, e, f, g, h, a, b, Add(K(0xbef9a3f7ul), w14, sigma1(w12), w7, sigma0(w15))); Round(b, c, d, e, f, g, h, a, Add(K(0xc67178f2ul), w15, sigma1(w13), w8, sigma0(w0))); // Output Write8(out, 0, Add(a, K(0x6a09e667ul))); Write8(out, 4, Add(b, K(0xbb67ae85ul))); Write8(out, 8, Add(c, K(0x3c6ef372ul))); Write8(out, 12, Add(d, K(0xa54ff53aul))); Write8(out, 16, Add(e, K(0x510e527ful))); Write8(out, 20, Add(f, K(0x9b05688cul))); Write8(out, 24, Add(g, K(0x1f83d9abul))); Write8(out, 28, Add(h, K(0x5be0cd19ul))); } } // namespace sha256d64_avx2 #endif diff --git a/src/crypto/sha256_sse41.cpp b/src/crypto/sha256_sse41.cpp index 3f2df68de..2f5a4dbda 100644 --- a/src/crypto/sha256_sse41.cpp +++ b/src/crypto/sha256_sse41.cpp @@ -1,443 +1,447 @@ +// Copyright (c) 2017-2019 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + #ifdef ENABLE_SSE41 #include #include #include namespace sha256d64_sse41 { namespace { __m128i inline K(uint32_t x) { return _mm_set1_epi32(x); } __m128i inline Add(__m128i x, __m128i y) { return _mm_add_epi32(x, y); } __m128i inline Add(__m128i x, __m128i y, __m128i z) { return Add(Add(x, y), z); } __m128i inline Add(__m128i x, __m128i y, __m128i z, __m128i w) { return Add(Add(x, y), Add(z, w)); } __m128i inline Add(__m128i x, __m128i y, __m128i z, __m128i w, __m128i v) { return Add(Add(x, y, z), Add(w, v)); } __m128i inline Inc(__m128i &x, __m128i y) { x = Add(x, y); return x; } __m128i inline Inc(__m128i &x, __m128i y, __m128i z) { x = Add(x, y, z); return x; } __m128i inline Inc(__m128i &x, __m128i y, __m128i z, __m128i w) { x = Add(x, y, z, w); return x; } __m128i inline Xor(__m128i x, __m128i y) { return _mm_xor_si128(x, y); } __m128i inline Xor(__m128i x, __m128i y, __m128i z) { return Xor(Xor(x, y), z); } __m128i inline Or(__m128i x, __m128i y) { return _mm_or_si128(x, y); } __m128i inline And(__m128i x, __m128i y) { return _mm_and_si128(x, y); } __m128i inline ShR(__m128i x, int n) { return _mm_srli_epi32(x, n); } __m128i inline ShL(__m128i x, int n) { return _mm_slli_epi32(x, n); } __m128i inline Ch(__m128i x, __m128i y, __m128i z) { return Xor(z, And(x, Xor(y, z))); } __m128i inline Maj(__m128i x, __m128i y, __m128i z) { return Or(And(x, y), And(z, Or(x, y))); } __m128i inline Sigma0(__m128i x) { return Xor(Or(ShR(x, 2), ShL(x, 30)), Or(ShR(x, 13), ShL(x, 19)), Or(ShR(x, 22), ShL(x, 10))); } __m128i inline Sigma1(__m128i x) { return Xor(Or(ShR(x, 6), ShL(x, 26)), Or(ShR(x, 11), ShL(x, 21)), Or(ShR(x, 25), ShL(x, 7))); } __m128i inline sigma0(__m128i x) { return Xor(Or(ShR(x, 7), ShL(x, 25)), Or(ShR(x, 18), ShL(x, 14)), ShR(x, 3)); } __m128i inline sigma1(__m128i x) { return Xor(Or(ShR(x, 17), ShL(x, 15)), Or(ShR(x, 19), ShL(x, 13)), ShR(x, 10)); } /** One round of SHA-256. */ inline void __attribute__((always_inline)) Round(__m128i a, __m128i b, __m128i c, __m128i &d, __m128i e, __m128i f, __m128i g, __m128i &h, __m128i k) { __m128i t1 = Add(h, Sigma1(e), Ch(e, f, g), k); __m128i t2 = Add(Sigma0(a), Maj(a, b, c)); d = Add(d, t1); h = Add(t1, t2); } __m128i inline Read4(const uint8_t *chunk, int offset) { __m128i ret = _mm_set_epi32( ReadLE32(chunk + 0 + offset), ReadLE32(chunk + 64 + offset), ReadLE32(chunk + 128 + offset), ReadLE32(chunk + 192 + offset)); return _mm_shuffle_epi8(ret, _mm_set_epi32(0x0C0D0E0FUL, 0x08090A0BUL, 0x04050607UL, 0x00010203UL)); } inline void Write4(uint8_t *out, int offset, __m128i v) { v = _mm_shuffle_epi8(v, _mm_set_epi32(0x0C0D0E0FUL, 0x08090A0BUL, 0x04050607UL, 0x00010203UL)); WriteLE32(out + 0 + offset, _mm_extract_epi32(v, 3)); WriteLE32(out + 32 + offset, _mm_extract_epi32(v, 2)); WriteLE32(out + 64 + offset, _mm_extract_epi32(v, 1)); WriteLE32(out + 96 + offset, _mm_extract_epi32(v, 0)); } } // namespace void Transform_4way(uint8_t *out, const uint8_t *in) { // Transform 1 __m128i a = K(0x6a09e667ul); __m128i b = K(0xbb67ae85ul); __m128i c = K(0x3c6ef372ul); __m128i d = K(0xa54ff53aul); __m128i e = K(0x510e527ful); __m128i f = K(0x9b05688cul); __m128i g = K(0x1f83d9abul); __m128i h = K(0x5be0cd19ul); __m128i w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; Round(a, b, c, d, e, f, g, h, Add(K(0x428a2f98ul), w0 = Read4(in, 0))); Round(h, a, b, c, d, e, f, g, Add(K(0x71374491ul), w1 = Read4(in, 4))); Round(g, h, a, b, c, d, e, f, Add(K(0xb5c0fbcful), w2 = Read4(in, 8))); Round(f, g, h, a, b, c, d, e, Add(K(0xe9b5dba5ul), w3 = Read4(in, 12))); Round(e, f, g, h, a, b, c, d, Add(K(0x3956c25bul), w4 = Read4(in, 16))); Round(d, e, f, g, h, a, b, c, Add(K(0x59f111f1ul), w5 = Read4(in, 20))); Round(c, d, e, f, g, h, a, b, Add(K(0x923f82a4ul), w6 = Read4(in, 24))); Round(b, c, d, e, f, g, h, a, Add(K(0xab1c5ed5ul), w7 = Read4(in, 28))); Round(a, b, c, d, e, f, g, h, Add(K(0xd807aa98ul), w8 = Read4(in, 32))); Round(h, a, b, c, d, e, f, g, Add(K(0x12835b01ul), w9 = Read4(in, 36))); Round(g, h, a, b, c, d, e, f, Add(K(0x243185beul), w10 = Read4(in, 40))); Round(f, g, h, a, b, c, d, e, Add(K(0x550c7dc3ul), w11 = Read4(in, 44))); Round(e, f, g, h, a, b, c, d, Add(K(0x72be5d74ul), w12 = Read4(in, 48))); Round(d, e, f, g, h, a, b, c, Add(K(0x80deb1feul), w13 = Read4(in, 52))); Round(c, d, e, f, g, h, a, b, Add(K(0x9bdc06a7ul), w14 = Read4(in, 56))); Round(b, c, d, e, f, g, h, a, Add(K(0xc19bf174ul), w15 = Read4(in, 60))); Round(a, b, c, d, e, f, g, h, Add(K(0xe49b69c1ul), Inc(w0, sigma1(w14), w9, sigma0(w1)))); Round(h, a, b, c, d, e, f, g, Add(K(0xefbe4786ul), Inc(w1, sigma1(w15), w10, sigma0(w2)))); Round(g, h, a, b, c, d, e, f, Add(K(0x0fc19dc6ul), Inc(w2, sigma1(w0), w11, sigma0(w3)))); Round(f, g, h, a, b, c, d, e, Add(K(0x240ca1ccul), Inc(w3, sigma1(w1), w12, sigma0(w4)))); Round(e, f, g, h, a, b, c, d, Add(K(0x2de92c6ful), Inc(w4, sigma1(w2), w13, sigma0(w5)))); Round(d, e, f, g, h, a, b, c, Add(K(0x4a7484aaul), Inc(w5, sigma1(w3), w14, sigma0(w6)))); Round(c, d, e, f, g, h, a, b, Add(K(0x5cb0a9dcul), Inc(w6, sigma1(w4), w15, sigma0(w7)))); Round(b, c, d, e, f, g, h, a, Add(K(0x76f988daul), Inc(w7, sigma1(w5), w0, sigma0(w8)))); Round(a, b, c, d, e, f, g, h, Add(K(0x983e5152ul), Inc(w8, sigma1(w6), w1, sigma0(w9)))); Round(h, a, b, c, d, e, f, g, Add(K(0xa831c66dul), Inc(w9, sigma1(w7), w2, sigma0(w10)))); Round(g, h, a, b, c, d, e, f, Add(K(0xb00327c8ul), Inc(w10, sigma1(w8), w3, sigma0(w11)))); Round(f, g, h, a, b, c, d, e, Add(K(0xbf597fc7ul), Inc(w11, sigma1(w9), w4, sigma0(w12)))); Round(e, f, g, h, a, b, c, d, Add(K(0xc6e00bf3ul), Inc(w12, sigma1(w10), w5, sigma0(w13)))); Round(d, e, f, g, h, a, b, c, Add(K(0xd5a79147ul), Inc(w13, sigma1(w11), w6, sigma0(w14)))); Round(c, d, e, f, g, h, a, b, Add(K(0x06ca6351ul), Inc(w14, sigma1(w12), w7, sigma0(w15)))); Round(b, c, d, e, f, g, h, a, Add(K(0x14292967ul), Inc(w15, sigma1(w13), w8, sigma0(w0)))); Round(a, b, c, d, e, f, g, h, Add(K(0x27b70a85ul), Inc(w0, sigma1(w14), w9, sigma0(w1)))); Round(h, a, b, c, d, e, f, g, Add(K(0x2e1b2138ul), Inc(w1, sigma1(w15), w10, sigma0(w2)))); Round(g, h, a, b, c, d, e, f, Add(K(0x4d2c6dfcul), Inc(w2, sigma1(w0), w11, sigma0(w3)))); Round(f, g, h, a, b, c, d, e, Add(K(0x53380d13ul), Inc(w3, sigma1(w1), w12, sigma0(w4)))); Round(e, f, g, h, a, b, c, d, Add(K(0x650a7354ul), Inc(w4, sigma1(w2), w13, sigma0(w5)))); Round(d, e, f, g, h, a, b, c, Add(K(0x766a0abbul), Inc(w5, sigma1(w3), w14, sigma0(w6)))); Round(c, d, e, f, g, h, a, b, Add(K(0x81c2c92eul), Inc(w6, sigma1(w4), w15, sigma0(w7)))); Round(b, c, d, e, f, g, h, a, Add(K(0x92722c85ul), Inc(w7, sigma1(w5), w0, sigma0(w8)))); Round(a, b, c, d, e, f, g, h, Add(K(0xa2bfe8a1ul), Inc(w8, sigma1(w6), w1, sigma0(w9)))); Round(h, a, b, c, d, e, f, g, Add(K(0xa81a664bul), Inc(w9, sigma1(w7), w2, sigma0(w10)))); Round(g, h, a, b, c, d, e, f, Add(K(0xc24b8b70ul), Inc(w10, sigma1(w8), w3, sigma0(w11)))); Round(f, g, h, a, b, c, d, e, Add(K(0xc76c51a3ul), Inc(w11, sigma1(w9), w4, sigma0(w12)))); Round(e, f, g, h, a, b, c, d, Add(K(0xd192e819ul), Inc(w12, sigma1(w10), w5, sigma0(w13)))); Round(d, e, f, g, h, a, b, c, Add(K(0xd6990624ul), Inc(w13, sigma1(w11), w6, sigma0(w14)))); Round(c, d, e, f, g, h, a, b, Add(K(0xf40e3585ul), Inc(w14, sigma1(w12), w7, sigma0(w15)))); Round(b, c, d, e, f, g, h, a, Add(K(0x106aa070ul), Inc(w15, sigma1(w13), w8, sigma0(w0)))); Round(a, b, c, d, e, f, g, h, Add(K(0x19a4c116ul), Inc(w0, sigma1(w14), w9, sigma0(w1)))); Round(h, a, b, c, d, e, f, g, Add(K(0x1e376c08ul), Inc(w1, sigma1(w15), w10, sigma0(w2)))); Round(g, h, a, b, c, d, e, f, Add(K(0x2748774cul), Inc(w2, sigma1(w0), w11, sigma0(w3)))); Round(f, g, h, a, b, c, d, e, Add(K(0x34b0bcb5ul), Inc(w3, sigma1(w1), w12, sigma0(w4)))); Round(e, f, g, h, a, b, c, d, Add(K(0x391c0cb3ul), Inc(w4, sigma1(w2), w13, sigma0(w5)))); Round(d, e, f, g, h, a, b, c, Add(K(0x4ed8aa4aul), Inc(w5, sigma1(w3), w14, sigma0(w6)))); Round(c, d, e, f, g, h, a, b, Add(K(0x5b9cca4ful), Inc(w6, sigma1(w4), w15, sigma0(w7)))); Round(b, c, d, e, f, g, h, a, Add(K(0x682e6ff3ul), Inc(w7, sigma1(w5), w0, sigma0(w8)))); Round(a, b, c, d, e, f, g, h, Add(K(0x748f82eeul), Inc(w8, sigma1(w6), w1, sigma0(w9)))); Round(h, a, b, c, d, e, f, g, Add(K(0x78a5636ful), Inc(w9, sigma1(w7), w2, sigma0(w10)))); Round(g, h, a, b, c, d, e, f, Add(K(0x84c87814ul), Inc(w10, sigma1(w8), w3, sigma0(w11)))); Round(f, g, h, a, b, c, d, e, Add(K(0x8cc70208ul), Inc(w11, sigma1(w9), w4, sigma0(w12)))); Round(e, f, g, h, a, b, c, d, Add(K(0x90befffaul), Inc(w12, sigma1(w10), w5, sigma0(w13)))); Round(d, e, f, g, h, a, b, c, Add(K(0xa4506cebul), Inc(w13, sigma1(w11), w6, sigma0(w14)))); Round(c, d, e, f, g, h, a, b, Add(K(0xbef9a3f7ul), Inc(w14, sigma1(w12), w7, sigma0(w15)))); Round(b, c, d, e, f, g, h, a, Add(K(0xc67178f2ul), Inc(w15, sigma1(w13), w8, sigma0(w0)))); a = Add(a, K(0x6a09e667ul)); b = Add(b, K(0xbb67ae85ul)); c = Add(c, K(0x3c6ef372ul)); d = Add(d, K(0xa54ff53aul)); e = Add(e, K(0x510e527ful)); f = Add(f, K(0x9b05688cul)); g = Add(g, K(0x1f83d9abul)); h = Add(h, K(0x5be0cd19ul)); __m128i t0 = a, t1 = b, t2 = c, t3 = d, t4 = e, t5 = f, t6 = g, t7 = h; // Transform 2 Round(a, b, c, d, e, f, g, h, K(0xc28a2f98ul)); Round(h, a, b, c, d, e, f, g, K(0x71374491ul)); Round(g, h, a, b, c, d, e, f, K(0xb5c0fbcful)); Round(f, g, h, a, b, c, d, e, K(0xe9b5dba5ul)); Round(e, f, g, h, a, b, c, d, K(0x3956c25bul)); Round(d, e, f, g, h, a, b, c, K(0x59f111f1ul)); Round(c, d, e, f, g, h, a, b, K(0x923f82a4ul)); Round(b, c, d, e, f, g, h, a, K(0xab1c5ed5ul)); Round(a, b, c, d, e, f, g, h, K(0xd807aa98ul)); Round(h, a, b, c, d, e, f, g, K(0x12835b01ul)); Round(g, h, a, b, c, d, e, f, K(0x243185beul)); Round(f, g, h, a, b, c, d, e, K(0x550c7dc3ul)); Round(e, f, g, h, a, b, c, d, K(0x72be5d74ul)); Round(d, e, f, g, h, a, b, c, K(0x80deb1feul)); Round(c, d, e, f, g, h, a, b, K(0x9bdc06a7ul)); Round(b, c, d, e, f, g, h, a, K(0xc19bf374ul)); Round(a, b, c, d, e, f, g, h, K(0x649b69c1ul)); Round(h, a, b, c, d, e, f, g, K(0xf0fe4786ul)); Round(g, h, a, b, c, d, e, f, K(0x0fe1edc6ul)); Round(f, g, h, a, b, c, d, e, K(0x240cf254ul)); Round(e, f, g, h, a, b, c, d, K(0x4fe9346ful)); Round(d, e, f, g, h, a, b, c, K(0x6cc984beul)); Round(c, d, e, f, g, h, a, b, K(0x61b9411eul)); Round(b, c, d, e, f, g, h, a, K(0x16f988faul)); Round(a, b, c, d, e, f, g, h, K(0xf2c65152ul)); Round(h, a, b, c, d, e, f, g, K(0xa88e5a6dul)); Round(g, h, a, b, c, d, e, f, K(0xb019fc65ul)); Round(f, g, h, a, b, c, d, e, K(0xb9d99ec7ul)); Round(e, f, g, h, a, b, c, d, K(0x9a1231c3ul)); Round(d, e, f, g, h, a, b, c, K(0xe70eeaa0ul)); Round(c, d, e, f, g, h, a, b, K(0xfdb1232bul)); Round(b, c, d, e, f, g, h, a, K(0xc7353eb0ul)); Round(a, b, c, d, e, f, g, h, K(0x3069bad5ul)); Round(h, a, b, c, d, e, f, g, K(0xcb976d5ful)); Round(g, h, a, b, c, d, e, f, K(0x5a0f118ful)); Round(f, g, h, a, b, c, d, e, K(0xdc1eeefdul)); Round(e, f, g, h, a, b, c, d, K(0x0a35b689ul)); Round(d, e, f, g, h, a, b, c, K(0xde0b7a04ul)); Round(c, d, e, f, g, h, a, b, K(0x58f4ca9dul)); Round(b, c, d, e, f, g, h, a, K(0xe15d5b16ul)); Round(a, b, c, d, e, f, g, h, K(0x007f3e86ul)); Round(h, a, b, c, d, e, f, g, K(0x37088980ul)); Round(g, h, a, b, c, d, e, f, K(0xa507ea32ul)); Round(f, g, h, a, b, c, d, e, K(0x6fab9537ul)); Round(e, f, g, h, a, b, c, d, K(0x17406110ul)); Round(d, e, f, g, h, a, b, c, K(0x0d8cd6f1ul)); Round(c, d, e, f, g, h, a, b, K(0xcdaa3b6dul)); Round(b, c, d, e, f, g, h, a, K(0xc0bbbe37ul)); Round(a, b, c, d, e, f, g, h, K(0x83613bdaul)); Round(h, a, b, c, d, e, f, g, K(0xdb48a363ul)); Round(g, h, a, b, c, d, e, f, K(0x0b02e931ul)); Round(f, g, h, a, b, c, d, e, K(0x6fd15ca7ul)); Round(e, f, g, h, a, b, c, d, K(0x521afacaul)); Round(d, e, f, g, h, a, b, c, K(0x31338431ul)); Round(c, d, e, f, g, h, a, b, K(0x6ed41a95ul)); Round(b, c, d, e, f, g, h, a, K(0x6d437890ul)); Round(a, b, c, d, e, f, g, h, K(0xc39c91f2ul)); Round(h, a, b, c, d, e, f, g, K(0x9eccabbdul)); Round(g, h, a, b, c, d, e, f, K(0xb5c9a0e6ul)); Round(f, g, h, a, b, c, d, e, K(0x532fb63cul)); Round(e, f, g, h, a, b, c, d, K(0xd2c741c6ul)); Round(d, e, f, g, h, a, b, c, K(0x07237ea3ul)); Round(c, d, e, f, g, h, a, b, K(0xa4954b68ul)); Round(b, c, d, e, f, g, h, a, K(0x4c191d76ul)); w0 = Add(t0, a); w1 = Add(t1, b); w2 = Add(t2, c); w3 = Add(t3, d); w4 = Add(t4, e); w5 = Add(t5, f); w6 = Add(t6, g); w7 = Add(t7, h); // Transform 3 a = K(0x6a09e667ul); b = K(0xbb67ae85ul); c = K(0x3c6ef372ul); d = K(0xa54ff53aul); e = K(0x510e527ful); f = K(0x9b05688cul); g = K(0x1f83d9abul); h = K(0x5be0cd19ul); Round(a, b, c, d, e, f, g, h, Add(K(0x428a2f98ul), w0)); Round(h, a, b, c, d, e, f, g, Add(K(0x71374491ul), w1)); Round(g, h, a, b, c, d, e, f, Add(K(0xb5c0fbcful), w2)); Round(f, g, h, a, b, c, d, e, Add(K(0xe9b5dba5ul), w3)); Round(e, f, g, h, a, b, c, d, Add(K(0x3956c25bul), w4)); Round(d, e, f, g, h, a, b, c, Add(K(0x59f111f1ul), w5)); Round(c, d, e, f, g, h, a, b, Add(K(0x923f82a4ul), w6)); Round(b, c, d, e, f, g, h, a, Add(K(0xab1c5ed5ul), w7)); Round(a, b, c, d, e, f, g, h, K(0x5807aa98ul)); Round(h, a, b, c, d, e, f, g, K(0x12835b01ul)); Round(g, h, a, b, c, d, e, f, K(0x243185beul)); Round(f, g, h, a, b, c, d, e, K(0x550c7dc3ul)); Round(e, f, g, h, a, b, c, d, K(0x72be5d74ul)); Round(d, e, f, g, h, a, b, c, K(0x80deb1feul)); Round(c, d, e, f, g, h, a, b, K(0x9bdc06a7ul)); Round(b, c, d, e, f, g, h, a, K(0xc19bf274ul)); Round(a, b, c, d, e, f, g, h, Add(K(0xe49b69c1ul), Inc(w0, sigma0(w1)))); Round(h, a, b, c, d, e, f, g, Add(K(0xefbe4786ul), Inc(w1, K(0xa00000ul), sigma0(w2)))); Round(g, h, a, b, c, d, e, f, Add(K(0x0fc19dc6ul), Inc(w2, sigma1(w0), sigma0(w3)))); Round(f, g, h, a, b, c, d, e, Add(K(0x240ca1ccul), Inc(w3, sigma1(w1), sigma0(w4)))); Round(e, f, g, h, a, b, c, d, Add(K(0x2de92c6ful), Inc(w4, sigma1(w2), sigma0(w5)))); Round(d, e, f, g, h, a, b, c, Add(K(0x4a7484aaul), Inc(w5, sigma1(w3), sigma0(w6)))); Round(c, d, e, f, g, h, a, b, Add(K(0x5cb0a9dcul), Inc(w6, sigma1(w4), K(0x100ul), sigma0(w7)))); Round(b, c, d, e, f, g, h, a, Add(K(0x76f988daul), Inc(w7, sigma1(w5), w0, K(0x11002000ul)))); Round(a, b, c, d, e, f, g, h, Add(K(0x983e5152ul), w8 = Add(K(0x80000000ul), sigma1(w6), w1))); Round(h, a, b, c, d, e, f, g, Add(K(0xa831c66dul), w9 = Add(sigma1(w7), w2))); Round(g, h, a, b, c, d, e, f, Add(K(0xb00327c8ul), w10 = Add(sigma1(w8), w3))); Round(f, g, h, a, b, c, d, e, Add(K(0xbf597fc7ul), w11 = Add(sigma1(w9), w4))); Round(e, f, g, h, a, b, c, d, Add(K(0xc6e00bf3ul), w12 = Add(sigma1(w10), w5))); Round(d, e, f, g, h, a, b, c, Add(K(0xd5a79147ul), w13 = Add(sigma1(w11), w6))); Round(c, d, e, f, g, h, a, b, Add(K(0x06ca6351ul), w14 = Add(sigma1(w12), w7, K(0x400022ul)))); Round(b, c, d, e, f, g, h, a, Add(K(0x14292967ul), w15 = Add(K(0x100ul), sigma1(w13), w8, sigma0(w0)))); Round(a, b, c, d, e, f, g, h, Add(K(0x27b70a85ul), Inc(w0, sigma1(w14), w9, sigma0(w1)))); Round(h, a, b, c, d, e, f, g, Add(K(0x2e1b2138ul), Inc(w1, sigma1(w15), w10, sigma0(w2)))); Round(g, h, a, b, c, d, e, f, Add(K(0x4d2c6dfcul), Inc(w2, sigma1(w0), w11, sigma0(w3)))); Round(f, g, h, a, b, c, d, e, Add(K(0x53380d13ul), Inc(w3, sigma1(w1), w12, sigma0(w4)))); Round(e, f, g, h, a, b, c, d, Add(K(0x650a7354ul), Inc(w4, sigma1(w2), w13, sigma0(w5)))); Round(d, e, f, g, h, a, b, c, Add(K(0x766a0abbul), Inc(w5, sigma1(w3), w14, sigma0(w6)))); Round(c, d, e, f, g, h, a, b, Add(K(0x81c2c92eul), Inc(w6, sigma1(w4), w15, sigma0(w7)))); Round(b, c, d, e, f, g, h, a, Add(K(0x92722c85ul), Inc(w7, sigma1(w5), w0, sigma0(w8)))); Round(a, b, c, d, e, f, g, h, Add(K(0xa2bfe8a1ul), Inc(w8, sigma1(w6), w1, sigma0(w9)))); Round(h, a, b, c, d, e, f, g, Add(K(0xa81a664bul), Inc(w9, sigma1(w7), w2, sigma0(w10)))); Round(g, h, a, b, c, d, e, f, Add(K(0xc24b8b70ul), Inc(w10, sigma1(w8), w3, sigma0(w11)))); Round(f, g, h, a, b, c, d, e, Add(K(0xc76c51a3ul), Inc(w11, sigma1(w9), w4, sigma0(w12)))); Round(e, f, g, h, a, b, c, d, Add(K(0xd192e819ul), Inc(w12, sigma1(w10), w5, sigma0(w13)))); Round(d, e, f, g, h, a, b, c, Add(K(0xd6990624ul), Inc(w13, sigma1(w11), w6, sigma0(w14)))); Round(c, d, e, f, g, h, a, b, Add(K(0xf40e3585ul), Inc(w14, sigma1(w12), w7, sigma0(w15)))); Round(b, c, d, e, f, g, h, a, Add(K(0x106aa070ul), Inc(w15, sigma1(w13), w8, sigma0(w0)))); Round(a, b, c, d, e, f, g, h, Add(K(0x19a4c116ul), Inc(w0, sigma1(w14), w9, sigma0(w1)))); Round(h, a, b, c, d, e, f, g, Add(K(0x1e376c08ul), Inc(w1, sigma1(w15), w10, sigma0(w2)))); Round(g, h, a, b, c, d, e, f, Add(K(0x2748774cul), Inc(w2, sigma1(w0), w11, sigma0(w3)))); Round(f, g, h, a, b, c, d, e, Add(K(0x34b0bcb5ul), Inc(w3, sigma1(w1), w12, sigma0(w4)))); Round(e, f, g, h, a, b, c, d, Add(K(0x391c0cb3ul), Inc(w4, sigma1(w2), w13, sigma0(w5)))); Round(d, e, f, g, h, a, b, c, Add(K(0x4ed8aa4aul), Inc(w5, sigma1(w3), w14, sigma0(w6)))); Round(c, d, e, f, g, h, a, b, Add(K(0x5b9cca4ful), Inc(w6, sigma1(w4), w15, sigma0(w7)))); Round(b, c, d, e, f, g, h, a, Add(K(0x682e6ff3ul), Inc(w7, sigma1(w5), w0, sigma0(w8)))); Round(a, b, c, d, e, f, g, h, Add(K(0x748f82eeul), Inc(w8, sigma1(w6), w1, sigma0(w9)))); Round(h, a, b, c, d, e, f, g, Add(K(0x78a5636ful), Inc(w9, sigma1(w7), w2, sigma0(w10)))); Round(g, h, a, b, c, d, e, f, Add(K(0x84c87814ul), Inc(w10, sigma1(w8), w3, sigma0(w11)))); Round(f, g, h, a, b, c, d, e, Add(K(0x8cc70208ul), Inc(w11, sigma1(w9), w4, sigma0(w12)))); Round(e, f, g, h, a, b, c, d, Add(K(0x90befffaul), Inc(w12, sigma1(w10), w5, sigma0(w13)))); Round(d, e, f, g, h, a, b, c, Add(K(0xa4506cebul), Inc(w13, sigma1(w11), w6, sigma0(w14)))); Round(c, d, e, f, g, h, a, b, Add(K(0xbef9a3f7ul), w14, sigma1(w12), w7, sigma0(w15))); Round(b, c, d, e, f, g, h, a, Add(K(0xc67178f2ul), w15, sigma1(w13), w8, sigma0(w0))); // Output Write4(out, 0, Add(a, K(0x6a09e667ul))); Write4(out, 4, Add(b, K(0xbb67ae85ul))); Write4(out, 8, Add(c, K(0x3c6ef372ul))); Write4(out, 12, Add(d, K(0xa54ff53aul))); Write4(out, 16, Add(e, K(0x510e527ful))); Write4(out, 20, Add(f, K(0x9b05688cul))); Write4(out, 24, Add(g, K(0x1f83d9abul))); Write4(out, 28, Add(h, K(0x5be0cd19ul))); } } // namespace sha256d64_sse41 #endif diff --git a/src/qt/test/addressbooktests.cpp b/src/qt/test/addressbooktests.cpp index 180cbc902..372af4540 100644 --- a/src/qt/test/addressbooktests.cpp +++ b/src/qt/test/addressbooktests.cpp @@ -1,170 +1,174 @@ +// Copyright (c) 2017-2021 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace { /** * Fill the edit address dialog box with data, submit it, and ensure that * the resulting message meets expectations. */ void EditAddressAndSubmit(EditAddressDialog *dialog, const QString &label, const QString &address, QString expected_msg) { QString warning_text; dialog->findChild("labelEdit")->setText(label); dialog->findChild("addressEdit")->setText(address); ConfirmMessage(&warning_text, 5); dialog->accept(); QCOMPARE(warning_text, expected_msg); } /** * Test adding various send addresses to the address book. * * There are three cases tested: * * - new_address: a new address which should add as a send address * successfully. * - existing_s_address: an existing sending address which won't add * successfully. * - existing_r_address: an existing receiving address which won't add * successfully. * * In each case, verify the resulting state of the address book and optionally * the warning message presented to the user. */ void TestAddAddressesToSendBook(interfaces::Node &node) { TestChain100Setup test; node.setContext(&test.m_node); std::shared_ptr wallet = std::make_shared(node.context()->chain.get(), WalletLocation(), CreateMockWalletDatabase()); wallet->SetupLegacyScriptPubKeyMan(); bool firstRun; wallet->LoadWallet(firstRun); auto build_address = [&wallet]() { CKey key; key.MakeNewKey(true); CTxDestination dest(GetDestinationForKey( key.GetPubKey(), wallet->m_default_address_type)); return std::make_pair( dest, QString::fromStdString(EncodeCashAddr(dest, Params()))); }; CTxDestination r_key_dest, s_key_dest; // Add a preexisting "receive" entry in the address book. QString preexisting_r_address; QString r_label("already here (r)"); // Add a preexisting "send" entry in the address book. QString preexisting_s_address; QString s_label("already here (s)"); // Define a new address (which should add to the address book successfully). QString new_address; std::tie(r_key_dest, preexisting_r_address) = build_address(); std::tie(s_key_dest, preexisting_s_address) = build_address(); std::tie(std::ignore, new_address) = build_address(); { LOCK(wallet->cs_wallet); wallet->SetAddressBook(r_key_dest, r_label.toStdString(), "receive"); wallet->SetAddressBook(s_key_dest, s_label.toStdString(), "send"); } auto check_addbook_size = [&wallet](int expected_size) { LOCK(wallet->cs_wallet); QCOMPARE(static_cast(wallet->m_address_book.size()), expected_size); }; // We should start with the two addresses we added earlier and nothing else. check_addbook_size(2); // Initialize relevant QT models. std::unique_ptr platformStyle( PlatformStyle::instantiate("other")); OptionsModel optionsModel; ClientModel clientModel(node, &optionsModel); AddWallet(wallet); WalletModel walletModel(interfaces::MakeWallet(wallet), clientModel, platformStyle.get()); RemoveWallet(wallet); EditAddressDialog editAddressDialog(EditAddressDialog::NewSendingAddress); editAddressDialog.setModel(walletModel.getAddressTableModel()); EditAddressAndSubmit( &editAddressDialog, QString("uhoh"), preexisting_r_address, QString( "Address \"%1\" already exists as a receiving address with label " "\"%2\" and so cannot be added as a sending address.") .arg(preexisting_r_address) .arg(r_label)); check_addbook_size(2); EditAddressAndSubmit( &editAddressDialog, QString("uhoh, different"), preexisting_s_address, QString( "The entered address \"%1\" is already in the address book with " "label \"%2\".") .arg(preexisting_s_address) .arg(s_label)); check_addbook_size(2); // Submit a new address which should add successfully - we expect the // warning message to be blank. EditAddressAndSubmit(&editAddressDialog, QString("new"), new_address, QString("")); check_addbook_size(3); } } // namespace void AddressBookTests::addressBookTests() { #ifdef Q_OS_MAC if (QApplication::platformName() == "minimal") { // Disable for mac on "minimal" platform to avoid crashes inside the Qt // framework when it tries to look up unimplemented cocoa functions, // and fails to handle returned nulls // (https://bugreports.qt.io/browse/QTBUG-49686). QWARN("Skipping AddressBookTests on mac build with 'minimal' platform " "set due to Qt bugs. To run AppTests, invoke with " "'QT_QPA_PLATFORM=cocoa test_bitcoin-qt' on mac, or else use a " "linux or windows build."); return; } #endif TestAddAddressesToSendBook(m_node); } diff --git a/src/qt/test/addressbooktests.h b/src/qt/test/addressbooktests.h index 932b1a2c8..32e5363c2 100644 --- a/src/qt/test/addressbooktests.h +++ b/src/qt/test/addressbooktests.h @@ -1,22 +1,26 @@ +// Copyright (c) 2018-2020 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + #ifndef BITCOIN_QT_TEST_ADDRESSBOOKTESTS_H #define BITCOIN_QT_TEST_ADDRESSBOOKTESTS_H #include #include namespace interfaces { class Node; } // namespace interfaces class AddressBookTests : public QObject { public: explicit AddressBookTests(interfaces::Node &node) : m_node(node) {} interfaces::Node &m_node; Q_OBJECT private Q_SLOTS: void addressBookTests(); }; #endif // BITCOIN_QT_TEST_ADDRESSBOOKTESTS_H diff --git a/src/qt/test/util.cpp b/src/qt/test/util.cpp index b5b90a057..b0d06f7bd 100644 --- a/src/qt/test/util.cpp +++ b/src/qt/test/util.cpp @@ -1,22 +1,26 @@ +// Copyright (c) 2018-2019 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + #include #include #include #include #include #include #include void ConfirmMessage(QString *text, int msec) { QTimer::singleShot(msec, [text] { for (QWidget *widget : QApplication::topLevelWidgets()) { if (widget->inherits("QMessageBox")) { QMessageBox *messageBox = qobject_cast(widget); if (text) { *text = messageBox->text(); } messageBox->defaultButton()->click(); } } }); } diff --git a/src/qt/test/util.h b/src/qt/test/util.h index caf4dc64a..da584f286 100644 --- a/src/qt/test/util.h +++ b/src/qt/test/util.h @@ -1,14 +1,18 @@ +// Copyright (c) 2018-2019 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + #ifndef BITCOIN_QT_TEST_UTIL_H #define BITCOIN_QT_TEST_UTIL_H class QString; /** * Press "Ok" button in message box dialog. * * @param text - Optionally store dialog text. * @param msec - Number of milliseconds to pause before triggering the callback. */ void ConfirmMessage(QString *text = nullptr, int msec = 0); #endif // BITCOIN_QT_TEST_UTIL_H diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp index 907d79640..b2d3cf661 100644 --- a/src/qt/test/wallettests.cpp +++ b/src/qt/test/wallettests.cpp @@ -1,277 +1,281 @@ +// Copyright (c) 2015-2021 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace { //! Press "Yes" or "Cancel" buttons in modal send confirmation dialog. void ConfirmSend(QString *text = nullptr, bool cancel = false) { QTimer::singleShot(0, Qt::PreciseTimer, [text, cancel]() { for (QWidget *widget : QApplication::topLevelWidgets()) { if (widget->inherits("SendConfirmationDialog")) { SendConfirmationDialog *dialog = qobject_cast(widget); if (text) { *text = dialog->text(); } QAbstractButton *button = dialog->button( cancel ? QMessageBox::Cancel : QMessageBox::Yes); button->setEnabled(true); button->click(); } } }); } //! Send coins to address and return txid. TxId SendCoins(CWallet &wallet, SendCoinsDialog &sendCoinsDialog, const CTxDestination &address, Amount amount) { QVBoxLayout *entries = sendCoinsDialog.findChild("entries"); SendCoinsEntry *entry = qobject_cast(entries->itemAt(0)->widget()); entry->findChild("payTo")->setText( QString::fromStdString(EncodeCashAddr(address, Params()))); entry->findChild("payAmount")->setValue(amount); TxId txid; boost::signals2::scoped_connection c = wallet.NotifyTransactionChanged.connect( [&txid](CWallet *, const TxId &hash, ChangeType status) { if (status == CT_NEW) { txid = hash; } }); ConfirmSend(); bool invoked = QMetaObject::invokeMethod(&sendCoinsDialog, "on_sendButton_clicked"); assert(invoked); return txid; } //! Find index of txid in transaction list. QModelIndex FindTx(const QAbstractItemModel &model, const uint256 &txid) { QString hash = QString::fromStdString(txid.ToString()); int rows = model.rowCount({}); for (int row = 0; row < rows; ++row) { QModelIndex index = model.index(row, 0, {}); if (model.data(index, TransactionTableModel::TxHashRole) == hash) { return index; } } return {}; } //! Simple qt wallet tests. // // Test widgets can be debugged interactively calling show() on them and // manually running the event loop, e.g.: // // sendCoinsDialog.show(); // QEventLoop().exec(); // // This also requires overriding the default minimal Qt platform: // // QT_QPA_PLATFORM=xcb src/qt/test/test_bitcoin-qt # Linux // QT_QPA_PLATFORM=windows src/qt/test/test_bitcoin-qt # Windows // QT_QPA_PLATFORM=cocoa src/qt/test/test_bitcoin-qt # macOS void TestGUI(interfaces::Node &node) { // Set up wallet and chain with 105 blocks (5 mature blocks for spending). TestChain100Setup test; for (int i = 0; i < 5; ++i) { test.CreateAndProcessBlock( {}, GetScriptForRawPubKey(test.coinbaseKey.GetPubKey())); } node.setContext(&test.m_node); std::shared_ptr wallet = std::make_shared(node.context()->chain.get(), WalletLocation(), CreateMockWalletDatabase()); bool firstRun; wallet->LoadWallet(firstRun); { auto spk_man = wallet->GetOrCreateLegacyScriptPubKeyMan(); LOCK2(wallet->cs_wallet, spk_man->cs_KeyStore); wallet->SetAddressBook( GetDestinationForKey(test.coinbaseKey.GetPubKey(), wallet->m_default_address_type), "", "receive"); spk_man->AddKeyPubKey(test.coinbaseKey, test.coinbaseKey.GetPubKey()); wallet->SetLastBlockProcessed(105, ::ChainActive().Tip()->GetBlockHash()); } { WalletRescanReserver reserver(*wallet); reserver.reserve(); CWallet::ScanResult result = wallet->ScanForWalletTransactions( Params().GetConsensus().hashGenesisBlock, 0 /* block height */, {} /* max height */, reserver, true /* fUpdate */); QCOMPARE(result.status, CWallet::ScanResult::SUCCESS); QCOMPARE(result.last_scanned_block, ::ChainActive().Tip()->GetBlockHash()); QVERIFY(result.last_failed_block.IsNull()); } wallet->SetBroadcastTransactions(true); // Create widgets for sending coins and listing transactions. std::unique_ptr platformStyle( PlatformStyle::instantiate("other")); OptionsModel optionsModel; ClientModel clientModel(node, &optionsModel); AddWallet(wallet); WalletModel walletModel(interfaces::MakeWallet(wallet), clientModel, platformStyle.get()); RemoveWallet(wallet); SendCoinsDialog sendCoinsDialog(platformStyle.get(), &walletModel); { // Check balance in send dialog QLabel *balanceLabel = sendCoinsDialog.findChild("labelBalance"); QString balanceText = balanceLabel->text(); int unit = walletModel.getOptionsModel()->getDisplayUnit(); Amount balance = walletModel.wallet().getBalance(); QString balanceComparison = BitcoinUnits::formatWithUnit( unit, balance, false, BitcoinUnits::separatorAlways); QCOMPARE(balanceText, balanceComparison); } // Send two transactions, and verify they are added to transaction list. TransactionTableModel *transactionTableModel = walletModel.getTransactionTableModel(); QCOMPARE(transactionTableModel->rowCount({}), 105); TxId txid1 = SendCoins(*wallet.get(), sendCoinsDialog, CTxDestination(PKHash()), 5 * COIN); TxId txid2 = SendCoins(*wallet.get(), sendCoinsDialog, CTxDestination(PKHash()), 10 * COIN); QCOMPARE(transactionTableModel->rowCount({}), 107); QVERIFY(FindTx(*transactionTableModel, txid1).isValid()); QVERIFY(FindTx(*transactionTableModel, txid2).isValid()); // Check current balance on OverviewPage OverviewPage overviewPage(platformStyle.get()); overviewPage.setWalletModel(&walletModel); QLabel *balanceLabel = overviewPage.findChild("labelBalance"); QString balanceText = balanceLabel->text(); int unit = walletModel.getOptionsModel()->getDisplayUnit(); Amount balance = walletModel.wallet().getBalance(); QString balanceComparison = BitcoinUnits::formatWithUnit( unit, balance, false, BitcoinUnits::separatorAlways); QCOMPARE(balanceText, balanceComparison); // Check Request Payment button ReceiveCoinsDialog receiveCoinsDialog(platformStyle.get()); receiveCoinsDialog.setModel(&walletModel); RecentRequestsTableModel *requestTableModel = walletModel.getRecentRequestsTableModel(); // Label input QLineEdit *labelInput = receiveCoinsDialog.findChild("reqLabel"); labelInput->setText("TEST_LABEL_1"); // Amount input BitcoinAmountField *amountInput = receiveCoinsDialog.findChild("reqAmount"); amountInput->setValue(1 * SATOSHI); // Message input QLineEdit *messageInput = receiveCoinsDialog.findChild("reqMessage"); messageInput->setText("TEST_MESSAGE_1"); int initialRowCount = requestTableModel->rowCount({}); QPushButton *requestPaymentButton = receiveCoinsDialog.findChild("receiveButton"); requestPaymentButton->click(); for (QWidget *widget : QApplication::topLevelWidgets()) { if (widget->inherits("ReceiveRequestDialog")) { ReceiveRequestDialog *receiveRequestDialog = qobject_cast(widget); QTextEdit *rlist = receiveRequestDialog->QObject::findChild("outUri"); QString paymentText = rlist->toPlainText(); QStringList paymentTextList = paymentText.split('\n'); QCOMPARE(paymentTextList.at(0), QString("Payment information")); QVERIFY(paymentTextList.at(1).indexOf(QString("URI: ecregtest:")) != -1); QVERIFY(paymentTextList.at(2).indexOf(QString("Address:")) != -1); QCOMPARE(paymentTextList.at(3), QString("Amount: 0.01 ") + QString::fromStdString(Currency::get().ticker)); QCOMPARE(paymentTextList.at(4), QString("Label: TEST_LABEL_1")); QCOMPARE(paymentTextList.at(5), QString("Message: TEST_MESSAGE_1")); } } // Clear button QPushButton *clearButton = receiveCoinsDialog.findChild("clearButton"); clearButton->click(); QCOMPARE(labelInput->text(), QString("")); QCOMPARE(amountInput->value(), Amount::zero()); QCOMPARE(messageInput->text(), QString("")); // Check addition to history int currentRowCount = requestTableModel->rowCount({}); QCOMPARE(currentRowCount, initialRowCount + 1); // Check Remove button QTableView *table = receiveCoinsDialog.findChild("recentRequestsView"); table->selectRow(currentRowCount - 1); QPushButton *removeRequestButton = receiveCoinsDialog.findChild("removeRequestButton"); removeRequestButton->click(); QCOMPARE(requestTableModel->rowCount({}), currentRowCount - 1); } } // namespace void WalletTests::walletTests() { #ifdef Q_OS_MAC if (QApplication::platformName() == "minimal") { // Disable for mac on "minimal" platform to avoid crashes inside the Qt // framework when it tries to look up unimplemented cocoa functions, // and fails to handle returned nulls // (https://bugreports.qt.io/browse/QTBUG-49686). QWARN( "Skipping WalletTests on mac build with 'minimal' platform set due " "to Qt bugs. To run AppTests, invoke with 'QT_QPA_PLATFORM=cocoa " "test_bitcoin-qt' on mac, or else use a linux or windows build."); return; } #endif TestGUI(m_node); } diff --git a/src/qt/test/wallettests.h b/src/qt/test/wallettests.h index 86e88ad44..eb2cd72b0 100644 --- a/src/qt/test/wallettests.h +++ b/src/qt/test/wallettests.h @@ -1,22 +1,26 @@ +// Copyright (c) 2017-2020 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + #ifndef BITCOIN_QT_TEST_WALLETTESTS_H #define BITCOIN_QT_TEST_WALLETTESTS_H #include #include namespace interfaces { class Node; } // namespace interfaces class WalletTests : public QObject { public: explicit WalletTests(interfaces::Node &node) : m_node(node) {} interfaces::Node &m_node; Q_OBJECT private Q_SLOTS: void walletTests(); }; #endif // BITCOIN_QT_TEST_WALLETTESTS_H diff --git a/src/test/blockchain_tests.cpp b/src/test/blockchain_tests.cpp index 8a817d688..5ac8a0923 100644 --- a/src/test/blockchain_tests.cpp +++ b/src/test/blockchain_tests.cpp @@ -1,70 +1,74 @@ +// Copyright (c) 2019-2021 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + #include #include #include #include #include #include /** * Equality between doubles is imprecise. Comparison should be done * with a small threshold of tolerance, rather than exact equality. */ static bool DoubleEquals(double a, double b, double epsilon) { return std::abs(a - b) < epsilon; } static CBlockIndex *CreateBlockIndexWithNbits(uint32_t nbits) { CBlockIndex *block_index = new CBlockIndex(); block_index->nHeight = 46367; block_index->nTime = 1269211443; block_index->nBits = nbits; return block_index; } static void RejectDifficultyMismatch(double difficulty, double expected_difficulty) { BOOST_CHECK_MESSAGE(DoubleEquals(difficulty, expected_difficulty, 0.00001), "Difficulty was " + ToString(difficulty) + " but was expected to be " + ToString(expected_difficulty)); } /** * Given a BlockIndex with the provided nbits, * verify that the expected difficulty results. */ static void TestDifficulty(uint32_t nbits, double expected_difficulty) { CBlockIndex *block_index = CreateBlockIndexWithNbits(nbits); double difficulty = GetDifficulty(block_index); delete block_index; RejectDifficultyMismatch(difficulty, expected_difficulty); } BOOST_FIXTURE_TEST_SUITE(blockchain_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(get_difficulty_for_very_low_target) { TestDifficulty(0x1f111111, 0.000001); } BOOST_AUTO_TEST_CASE(get_difficulty_for_low_target) { TestDifficulty(0x1ef88f6f, 0.000016); } BOOST_AUTO_TEST_CASE(get_difficulty_for_mid_target) { TestDifficulty(0x1df88f6f, 0.004023); } BOOST_AUTO_TEST_CASE(get_difficulty_for_high_target) { TestDifficulty(0x1cf88f6f, 1.029916); } BOOST_AUTO_TEST_CASE(get_difficulty_for_very_high_target) { TestDifficulty(0x12345678, 5913134931067755359633408.0); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/functional/combine_logs.py b/test/functional/combine_logs.py index af401e5d8..a5b832bbc 100755 --- a/test/functional/combine_logs.py +++ b/test/functional/combine_logs.py @@ -1,220 +1,223 @@ #!/usr/bin/env python3 +# Copyright (c) 2017-2020 The Bitcoin developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. """Combine logs from multiple bitcoin nodes as well as the test_framework log. This streams the combined log output to stdout. Use combine_logs.py > outputfile to write to an outputfile. If no argument is provided, the most recent test directory will be used.""" import argparse from collections import defaultdict, namedtuple import heapq import itertools import os import pathlib import re import sys import tempfile # N.B.: don't import any local modules here - this script must remain executable # without the parent module installed. # Should match same symbol in `test_framework.test_framework`. TMPDIR_PREFIX = "bitcoin_func_test_" # Matches on the date format at the start of the log event TIMESTAMP_PATTERN = re.compile( r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{6})?Z") LogEvent = namedtuple('LogEvent', ['timestamp', 'source', 'event']) def main(): """Main function. Parses args, reads the log files and renders them as text or html.""" parser = argparse.ArgumentParser( description=__doc__, formatter_class=argparse.RawTextHelpFormatter) parser.add_argument( 'testdir', nargs='?', default='', help='temporary test directory to combine logs from. ' 'Defaults to the most recent') parser.add_argument('-c', '--color', dest='color', action='store_true', help='outputs the combined log with events colored by ' 'source (requires posix terminal colors. Use less' ' -r for viewing)') parser.add_argument('--html', dest='html', action='store_true', help='outputs the combined log as html. ' 'Requires jinja2. pip install jinja2') args = parser.parse_args() if args.html and args.color: print("Only one out of --color or --html should be specified") sys.exit(1) testdir = args.testdir or find_latest_test_dir() if not testdir: print("No test directories found") sys.exit(1) if not args.testdir: print("Opening latest test directory: {}".format(testdir), file=sys.stderr) colors = defaultdict(lambda: '') if args.color: colors["test"] = "\033[0;36m" # CYAN colors["node0"] = "\033[0;34m" # BLUE colors["node1"] = "\033[0;32m" # GREEN colors["node2"] = "\033[0;31m" # RED colors["node3"] = "\033[0;33m" # YELLOW colors["reset"] = "\033[0m" # Reset font color log_events = read_logs(testdir) if args.html: print_logs_html(log_events) else: print_logs_plain(log_events, colors) print_node_warnings(testdir, colors) def read_logs(tmp_dir): """Reads log files. Delegates to generator function get_log_events() to provide individual log events for each of the input log files.""" # Find out what the folder is called that holds the debug.log file glob = pathlib.Path(tmp_dir).glob('node0/**/debug.log') path = next(glob, None) if path: # more than one debug.log should never happen assert next(glob, None) is None # extract the chain name chain = re.search(r'node0/(.+?)/debug\.log$', path.as_posix()).group(1) else: # fallback to regtest (should only happen when none exists) chain = 'regtest' files = [("test", "{}/test_framework.log".format(tmp_dir))] for i in itertools.count(): logfile = "{}/node{}/{}/debug.log".format(tmp_dir, i, chain) if not os.path.isfile(logfile): break files.append(("node{}".format(i), logfile)) return heapq.merge(*[get_log_events(source, f) for source, f in files]) def print_node_warnings(tmp_dir, colors): """Print nodes' errors and warnings""" warnings = [] for stream in ['stdout', 'stderr']: for i in itertools.count(): folder = "{}/node{}/{}".format(tmp_dir, i, stream) if not os.path.isdir(folder): break for (_, _, fns) in os.walk(folder): for fn in fns: warning = pathlib.Path( '{}/{}'.format(folder, fn)).read_text().strip() if warning: warnings.append(("node{} {}".format(i, stream), warning)) print() for w in warnings: print("{} {} {} {}".format(colors[w[0].split()[0]], w[0], w[1], colors["reset"])) def find_latest_test_dir(): """Returns the latest tmpfile test directory prefix.""" tmpdir = tempfile.gettempdir() def join_tmp(basename): return os.path.join(tmpdir, basename) def is_valid_test_tmpdir(basename): fullpath = join_tmp(basename) return ( os.path.isdir(fullpath) and basename.startswith(TMPDIR_PREFIX) and os.access(fullpath, os.R_OK) ) testdir_paths = [join_tmp(name) for name in os.listdir(tmpdir) if is_valid_test_tmpdir(name)] return max(testdir_paths, key=os.path.getmtime) if testdir_paths else None def get_log_events(source, logfile): """Generator function that returns individual log events. Log events may be split over multiple lines. We use the timestamp regex match as the marker for a new log event.""" try: with open(logfile, 'r', encoding='utf-8') as infile: event = '' timestamp = '' for line in infile: # skip blank lines if line == '\n': continue # if this line has a timestamp, it's the start of a new log # event. time_match = TIMESTAMP_PATTERN.match(line) if time_match: if event: yield LogEvent(timestamp=timestamp, source=source, event=event.rstrip()) timestamp = time_match.group() if time_match.group(1) is None: # timestamp does not have microseconds. Add zeroes. timestamp_micro = timestamp.replace("Z", ".000000Z") line = line.replace(timestamp, timestamp_micro) timestamp = timestamp_micro event = line # if it doesn't have a timestamp, it's a continuation line of # the previous log. else: # Add the line. Prefix with space equivalent to the source # + timestamp so log lines are aligned event += " " + line # Flush the final event yield LogEvent(timestamp=timestamp, source=source, event=event.rstrip()) except FileNotFoundError: print("File {} could not be opened. Continuing without it.".format( logfile), file=sys.stderr) def print_logs_plain(log_events, colors): """Renders the iterator of log events into text.""" for event in log_events: lines = event.event.splitlines() print("{0} {1: <5} {2} {3}".format(colors[event.source.rstrip()], event.source, lines[0], colors["reset"])) if len(lines) > 1: for line in lines[1:]: print("{0}{1}{2}".format( colors[event.source.rstrip()], line, colors["reset"])) def print_logs_html(log_events): """Renders the iterator of log events into html.""" try: import jinja2 except ImportError: print("jinja2 not found. Try `pip install jinja2`") sys.exit(1) print(jinja2.Environment(loader=jinja2.FileSystemLoader('./')) .get_template('combined_log_template.html') .render(title="Combined Logs from testcase", log_events=[event._asdict() for event in log_events])) if __name__ == '__main__': main()