diff --git a/.github/workflows/build-src.yml b/.github/workflows/build-src.yml index 9af8b19b2e00..6f9d3279b845 100644 --- a/.github/workflows/build-src.yml +++ b/.github/workflows/build-src.yml @@ -76,7 +76,7 @@ jobs: - name: Build source run: | - CCACHE_SIZE="400M" + CCACHE_MAXSIZE="400M" CACHE_DIR="/cache" mkdir /output BASE_OUTDIR="/output" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 224d7988ecc3..4e9b6c9efa8b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,8 +18,29 @@ concurrency: cancel-in-progress: ${{ github.ref_type != 'tag' }} jobs: + check-skip: + name: Check skip conditions + runs-on: ubuntu-latest + outputs: + skip: ${{ steps.skip-check.outputs.skip }} + steps: + - name: Check skip environment variables + id: skip-check + run: | + if [[ "${{ github.event_name }}" == "push" && "${{ vars.SKIP_ON_PUSH }}" != "" ]]; then + echo "Skipping build on push due to SKIP_ON_PUSH environment variable" + echo "skip=true" >> $GITHUB_OUTPUT + elif [[ "${{ github.event_name }}" == "pull_request_target" && "${{ vars.SKIP_ON_PR }}" != "" ]]; then + echo "Skipping build on pull request due to SKIP_ON_PR environment variable" + echo "skip=true" >> $GITHUB_OUTPUT + else + echo "skip=false" >> $GITHUB_OUTPUT + fi + container: name: Build container + needs: [check-skip] + if: ${{ needs.check-skip.outputs.skip == 'false' }} uses: ./.github/workflows/build-container.yml with: context: ./contrib/containers/ci @@ -28,6 +49,8 @@ jobs: container-slim: name: Build slim container + needs: [check-skip] + if: ${{ needs.check-skip.outputs.skip == 'false' }} uses: ./.github/workflows/build-container.yml with: context: ./contrib/containers/ci diff --git a/.gitignore b/.gitignore index 023edd5f3498..ca8ffafefcfc 100644 --- a/.gitignore +++ b/.gitignore @@ -168,3 +168,7 @@ test/lint/.cppcheck/* # flake8 cache location .cache/* + +# Editor and tooling +.vscode/ +compile_commands.json diff --git a/.tx/config b/.tx/config index 7699aee5fffe..a9939bf4f9cd 100644 --- a/.tx/config +++ b/.tx/config @@ -1,7 +1,7 @@ [main] host = https://www.transifex.com -[dash.dash_ents] +[o:dash:p:dash:r:dash_ents] file_filter = src/qt/locale/dash_.ts source_file = src/qt/locale/dash_en.xlf source_lang = en diff --git a/ci/dash/build_src.sh b/ci/dash/build_src.sh index 3ebdc910dea2..ad1201e4599d 100755 --- a/ci/dash/build_src.sh +++ b/ci/dash/build_src.sh @@ -27,7 +27,7 @@ if [ "$CHECK_DOC" = 1 ]; then test/lint/all-lint.py fi -ccache --zero-stats --max-size="$CCACHE_SIZE" +ccache --zero-stats if [ -n "$CONFIG_SHELL" ]; then export CONFIG_SHELL="$CONFIG_SHELL" diff --git a/ci/dash/lint-tidy.sh b/ci/dash/lint-tidy.sh index 7786a58f7ef9..d417d0009b90 100755 --- a/ci/dash/lint-tidy.sh +++ b/ci/dash/lint-tidy.sh @@ -12,7 +12,11 @@ set -eo pipefail # that *before* running this script. cd "${BASE_ROOT_DIR}/build-ci/dashcore-${BUILD_TARGET}/src" -( run-clang-tidy -quiet "${MAKEJOBS}" ) | grep -C5 "error" +if ! ( run-clang-tidy -quiet "${MAKEJOBS}" | tee tmp.tidy-out.txt ); then + grep -C5 "error: " tmp.tidy-out.txt + echo "^^^ ⚠️ Failure generated from clang-tidy" + false +fi cd "${BASE_ROOT_DIR}/build-ci/dashcore-${BUILD_TARGET}" iwyu_tool.py \ @@ -20,8 +24,10 @@ iwyu_tool.py \ "src/init" \ "src/rpc/fees.cpp" \ "src/rpc/signmessage.cpp" \ + "src/test/fuzz/txorphan.cpp" \ "src/util/bip32.cpp" \ "src/util/bytevectorhash.cpp" \ + "src/util/check.cpp" \ "src/util/error.cpp" \ "src/util/getuniquepath.cpp" \ "src/util/hasher.cpp" \ diff --git a/ci/lint/04_install.sh b/ci/lint/04_install.sh index bcd636641f7f..431672ba1fb3 100755 --- a/ci/lint/04_install.sh +++ b/ci/lint/04_install.sh @@ -35,6 +35,7 @@ fi ${CI_RETRY_EXE} pip3 install codespell==2.0.0 ${CI_RETRY_EXE} pip3 install flake8==3.8.3 +${CI_RETRY_EXE} pip3 install lief==0.13.1 ${CI_RETRY_EXE} pip3 install mypy==0.910 ${CI_RETRY_EXE} pip3 install pyzmq==22.3.0 ${CI_RETRY_EXE} pip3 install vulture==2.3 diff --git a/ci/test/00_setup_env.sh b/ci/test/00_setup_env.sh index d4840e9ebfd8..9ff3c333754e 100755 --- a/ci/test/00_setup_env.sh +++ b/ci/test/00_setup_env.sh @@ -55,7 +55,7 @@ export BOOST_TEST_RANDOM=${BOOST_TEST_RANDOM:-1} export DEBIAN_FRONTEND=noninteractive export HOST_CACHE_DIR=${HOST_CACHE_DIR:-$BASE_ROOT_DIR/ci-cache-$BUILD_TARGET} export CACHE_DIR=${CACHE_DIR:-$HOST_CACHE_DIR} -export CCACHE_SIZE=${CCACHE_SIZE:-100M} +export CCACHE_MAXSIZE=${CCACHE_MAXSIZE:-100M} export CCACHE_TEMPDIR=${CCACHE_TEMPDIR:-/tmp/.ccache-temp} export CCACHE_COMPRESS=${CCACHE_COMPRESS:-1} # The cache dir. diff --git a/ci/test/00_setup_env_mac_native_x86_64.sh b/ci/test/00_setup_env_mac_native_x86_64.sh index 0ac2d62eb6c5..252b95c2178f 100755 --- a/ci/test/00_setup_env_mac_native_x86_64.sh +++ b/ci/test/00_setup_env_mac_native_x86_64.sh @@ -14,6 +14,6 @@ export BITCOIN_CONFIG="--with-gui --enable-reduce-exports --disable-miner --with export CI_OS_NAME="macos" export NO_DEPENDS=1 export OSX_SDK="" -export CCACHE_SIZE=300M +export CCACHE_MAXSIZE=300M export RUN_SECURITY_TESTS="true" diff --git a/ci/test/00_setup_env_native_fuzz_with_valgrind.sh b/ci/test/00_setup_env_native_fuzz_with_valgrind.sh index 1b5728feb84c..f379d8ee7edc 100755 --- a/ci/test/00_setup_env_native_fuzz_with_valgrind.sh +++ b/ci/test/00_setup_env_native_fuzz_with_valgrind.sh @@ -7,7 +7,7 @@ export LC_ALL=C.UTF-8 export CONTAINER_NAME=ci_native_fuzz_valgrind -export PACKAGES="clang llvm python3 libevent-dev bsdmainutils libboost-dev valgrind" +export PACKAGES="clang llvm libclang-rt-dev python3 libevent-dev bsdmainutils libboost-dev valgrind" export NO_DEPENDS=1 export RUN_UNIT_TESTS=false export RUN_FUNCTIONAL_TESTS=false @@ -16,4 +16,4 @@ export FUZZ_TESTS_CONFIG="--valgrind" export GOAL="install" # Temporarily pin dwarf 4, until valgrind can understand clang's dwarf 5 export BITCOIN_CONFIG="--enable-fuzz --with-sanitizers=fuzzer CC=clang-18 CXX=clang++-18 CFLAGS='-gdwarf-4' CXXFLAGS='-gdwarf-4'" -export CCACHE_SIZE=200M +export CCACHE_MAXSIZE=200M diff --git a/ci/test/00_setup_env_native_valgrind.sh b/ci/test/00_setup_env_native_valgrind.sh index d0a217a1f659..d7bf8b2f3550 100755 --- a/ci/test/00_setup_env_native_valgrind.sh +++ b/ci/test/00_setup_env_native_valgrind.sh @@ -6,7 +6,7 @@ export LC_ALL=C.UTF-8 -export PACKAGES="valgrind clang llvm python3-zmq libevent-dev bsdmainutils libboost-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev" +export PACKAGES="valgrind clang llvm libclang-rt-dev python3-zmq libevent-dev bsdmainutils libboost-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev" export USE_VALGRIND=1 export NO_DEPENDS=1 export TEST_RUNNER_EXTRA="--exclude rpc_bind,feature_bind_extra --timeout-factor=4" # Excluded for now, see https://github.com/bitcoin/bitcoin/issues/17765#issuecomment-602068547 diff --git a/ci/test/04_install.sh b/ci/test/04_install.sh index 3ea6d24e6b86..40d70b0394f8 100755 --- a/ci/test/04_install.sh +++ b/ci/test/04_install.sh @@ -61,6 +61,9 @@ if [ -z "$DANGER_RUN_CI_ON_HOST" ]; then docker exec "$DOCKER_ID" chown -R "$LOCAL_USER":"$LOCAL_USER" "${BASE_ROOT_DIR}" export DOCKER_CI_CMD_PREFIX_ROOT="docker exec -u 0 $DOCKER_ID" export DOCKER_CI_CMD_PREFIX="docker exec -u $LOCAL_UID $DOCKER_ID" + # Fixes permission issues when there is a container UID/GID mismatch with the owner + # of the mounted dash src dir. + $DOCKER_CI_CMD_PREFIX_ROOT git config --global --add safe.directory "*" else echo "Running on host system without docker wrapper" fi @@ -97,7 +100,7 @@ if [ "$CI_OS_NAME" == "macos" ]; then echo "Number of CPUs: $(sysctl -n hw.logicalcpu)" else CI_EXEC free -m -h - CI_EXEC echo "Number of CPUs \(nproc\):" \$\(nproc\) + CI_EXEC echo "Number of CPUs (nproc): $(nproc)" CI_EXEC echo "$(lscpu | grep Endian)" fi CI_EXEC echo "Free disk space:" diff --git a/configure.ac b/configure.ac index 11f4fe2c215b..6bf3a3205718 100644 --- a/configure.ac +++ b/configure.ac @@ -378,6 +378,9 @@ if test "$enable_debug" = "yes"; then AX_CHECK_PREPROC_FLAG([-DABORT_ON_FAILED_ASSUME], [DEBUG_CPPFLAGS="$DEBUG_CPPFLAGS -DABORT_ON_FAILED_ASSUME"], [], [$CXXFLAG_WERROR]) AX_CHECK_COMPILE_FLAG([-ftrapv], [DEBUG_CXXFLAGS="$DEBUG_CXXFLAGS -ftrapv"], [], [$CXXFLAG_WERROR]) else + dnl If not debugging, enable more aggressive optimizations for sphlib sources + AX_CHECK_COMPILE_FLAG([-O3], [SPHLIB_CFLAGS="$SPHLIB_CFLAGS -O3"], [], [$CXXFLAG_WERROR]) + # We always enable at at least -g1 debug info to support proper stacktraces in crash infos # Stacktraces will be suboptimal due to optimization, but better than nothing. Also, -fno-omit-frame-pointer # mitigates this a little bit @@ -1874,6 +1877,7 @@ AC_SUBST(PIC_FLAGS) AC_SUBST(PIE_FLAGS) AC_SUBST(SANITIZER_CXXFLAGS) AC_SUBST(SANITIZER_LDFLAGS) +AC_SUBST(SPHLIB_CFLAGS) AC_SUBST(SSE42_CXXFLAGS) AC_SUBST(SSE41_CXXFLAGS) AC_SUBST(CLMUL_CXXFLAGS) diff --git a/contrib/dash-cli.bash-completion b/contrib/dash-cli.bash similarity index 100% rename from contrib/dash-cli.bash-completion rename to contrib/dash-cli.bash diff --git a/contrib/dash-tx.bash-completion b/contrib/dash-tx.bash similarity index 100% rename from contrib/dash-tx.bash-completion rename to contrib/dash-tx.bash diff --git a/contrib/dashd.bash-completion b/contrib/dashd.bash similarity index 100% rename from contrib/dashd.bash-completion rename to contrib/dashd.bash diff --git a/contrib/debian/copyright b/contrib/debian/copyright index 10a68e74ac75..af24c9c258e5 100644 --- a/contrib/debian/copyright +++ b/contrib/debian/copyright @@ -7,10 +7,10 @@ Files: * Copyright: 2009-2025, Bitcoin Core Developers, 2019-2025, Dash Core Developers License: Expat -Comment: The Bitcoin Core Developers encompasses the current developers listed on bitcoin.org, - as well as the numerous contributors to the project. The Dash Core Developers - encompasses the current developers listed on https://www.dash.org/team/, as well as - the numerous contributors to the project. +Comment: The Bitcoin Core Developers encompasses all contributors to the + project, listed in the release notes or the git log. The Dash Core + Developers encompasses all contributors to the project, listed in the + release notes or the git log. Files: debian/* Copyright: 2010-2011, Jonas Smedegaard diff --git a/contrib/devtools/copyright_header.py b/contrib/devtools/copyright_header.py index 540e0fd5713c..c18c156d5f5e 100755 --- a/contrib/devtools/copyright_header.py +++ b/contrib/devtools/copyright_header.py @@ -25,7 +25,6 @@ 'src/ctpl_stl.h', 'src/test/fuzz/FuzzedDataProvider.h', 'src/tinyformat.h', - 'src/util/expected.h', 'src/wallet/bip39.cpp', 'src/wallet/bip39.h', 'src/wallet/bip39_english.h', diff --git a/contrib/devtools/security-check.py b/contrib/devtools/security-check.py index 2cbb861d57c3..001e46ceeef7 100755 --- a/contrib/devtools/security-check.py +++ b/contrib/devtools/security-check.py @@ -10,7 +10,7 @@ import sys from typing import List -import lief #type:ignore +import lief def check_ELF_RELRO(binary) -> bool: ''' diff --git a/contrib/devtools/symbol-check.py b/contrib/devtools/symbol-check.py index d6bdb193eb64..a89cd32e83d2 100755 --- a/contrib/devtools/symbol-check.py +++ b/contrib/devtools/symbol-check.py @@ -13,7 +13,7 @@ import sys from typing import Dict, List -import lief #type:ignore +import lief # Debian 11 (Bullseye) EOL: 2026. https://wiki.debian.org/LTS # diff --git a/contrib/devtools/test-security-check.py b/contrib/devtools/test-security-check.py index 5d9dc169045a..035a6e696877 100755 --- a/contrib/devtools/test-security-check.py +++ b/contrib/devtools/test-security-check.py @@ -5,7 +5,7 @@ ''' Test script for security-check.py ''' -import lief #type:ignore +import lief import os import subprocess from typing import List diff --git a/contrib/testgen/README.md b/contrib/testgen/README.md index 4d9054095571..1efe07d483a0 100644 --- a/contrib/testgen/README.md +++ b/contrib/testgen/README.md @@ -4,5 +4,5 @@ Utilities to generate test vectors for the data-driven Dash tests. Usage: - PYTHONPATH=../../test/functional/test_framework ./gen_key_io_test_vectors.py valid 50 > ../../src/test/data/key_io_valid.json - PYTHONPATH=../../test/functional/test_framework ./gen_key_io_test_vectors.py invalid 50 > ../../src/test/data/key_io_invalid.json + ./gen_key_io_test_vectors.py valid 50 > ../../src/test/data/key_io_valid.json + ./gen_key_io_test_vectors.py invalid 50 > ../../src/test/data/key_io_invalid.json diff --git a/contrib/testgen/base58.py b/contrib/testgen/base58.py deleted file mode 100644 index 87341ccf96dc..000000000000 --- a/contrib/testgen/base58.py +++ /dev/null @@ -1,115 +0,0 @@ -# Copyright (c) 2012-2020 The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. -''' -Bitcoin base58 encoding and decoding. - -Based on https://bitcointalk.org/index.php?topic=1026.0 (public domain) -''' -import hashlib - -# for compatibility with following code... -class SHA256: - new = hashlib.sha256 - -if str != bytes: - # Python 3.x - def ord(c): - return c - def chr(n): - return bytes( (n,) ) - -__b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' -__b58base = len(__b58chars) -b58chars = __b58chars - -def b58encode(v): - """ encode v, which is a string of bytes, to base58. - """ - long_value = 0 - for (i, c) in enumerate(v[::-1]): - if isinstance(c, str): - c = ord(c) - long_value += (256**i) * c - - result = '' - while long_value >= __b58base: - div, mod = divmod(long_value, __b58base) - result = __b58chars[mod] + result - long_value = div - result = __b58chars[long_value] + result - - # Bitcoin does a little leading-zero-compression: - # leading 0-bytes in the input become leading-1s - nPad = 0 - for c in v: - if c == 0: - nPad += 1 - else: - break - - return (__b58chars[0]*nPad) + result - -def b58decode(v, length = None): - """ decode v into a string of len bytes - """ - long_value = 0 - for i, c in enumerate(v[::-1]): - pos = __b58chars.find(c) - assert pos != -1 - long_value += pos * (__b58base**i) - - result = bytes() - while long_value >= 256: - div, mod = divmod(long_value, 256) - result = chr(mod) + result - long_value = div - result = chr(long_value) + result - - nPad = 0 - for c in v: - if c == __b58chars[0]: - nPad += 1 - continue - break - - result = bytes(nPad) + result - if length is not None and len(result) != length: - return None - - return result - -def checksum(v): - """Return 32-bit checksum based on SHA256""" - return SHA256.new(SHA256.new(v).digest()).digest()[0:4] - -def b58encode_chk(v): - """b58encode a string, with 32-bit checksum""" - return b58encode(v + checksum(v)) - -def b58decode_chk(v): - """decode a base58 string, check and remove checksum""" - result = b58decode(v) - if result is None: - return None - if result[-4:] == checksum(result[:-4]): - return result[:-4] - else: - return None - -def get_bcaddress_version(strAddress): - """ Returns None if strAddress is invalid. Otherwise returns integer version of address. """ - addr = b58decode_chk(strAddress) - if addr is None or len(addr)!=21: - return None - version = addr[0] - return ord(version) - -if __name__ == '__main__': - # Test case (from http://gitorious.org/bitcoin/python-base58.git) - assert get_bcaddress_version('15VjRaDX9zpbA8LVnbrCAFzrVzN7ixHNsC') == 0 - _ohai = 'o hai'.encode('ascii') - _tmp = b58encode(_ohai) - assert _tmp == 'DYB3oMS' - assert b58decode(_tmp, 5) == _ohai - print("Tests passed") diff --git a/contrib/testgen/gen_key_io_test_vectors.py b/contrib/testgen/gen_key_io_test_vectors.py index 94f798081975..ba045ec1c505 100755 --- a/contrib/testgen/gen_key_io_test_vectors.py +++ b/contrib/testgen/gen_key_io_test_vectors.py @@ -1,20 +1,24 @@ #!/usr/bin/env python3 -# Copyright (c) 2012-2021 The Bitcoin Core developers +# Copyright (c) 2012-2022 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. ''' Generate valid and invalid base58 address and private key test vectors. Usage: - PYTHONPATH=../../test/functional/test_framework ./gen_key_io_test_vectors.py valid 50 > ../../src/test/data/key_io_valid.json - PYTHONPATH=../../test/functional/test_framework ./gen_key_io_test_vectors.py invalid 50 > ../../src/test/data/key_io_invalid.json + ./gen_key_io_test_vectors.py valid 50 > ../../src/test/data/key_io_valid.json + ./gen_key_io_test_vectors.py invalid 50 > ../../src/test/data/key_io_invalid.json ''' -# 2012 Wladimir J. van der Laan -# Released under MIT License -import os + from itertools import islice -from base58 import b58encode_chk, b58decode_chk, b58chars +import os import random +import sys + +sys.path.append(os.path.join(os.path.dirname(__file__), '../../test/functional')) + +from test_framework.address import base58_to_byte, byte_to_base58, b58chars # noqa: E402 +from test_framework.script import OP_DUP, OP_EQUAL, OP_EQUALVERIFY, OP_HASH160, OP_CHECKSIG # noqa: E402 # key types PUBKEY_ADDRESS = 76 @@ -28,15 +32,6 @@ PRIVKEY_REGTEST = 239 # script -OP_0 = 0x00 -OP_1 = 0x51 -OP_2 = 0x52 -OP_16 = 0x60 -OP_DUP = 0x76 -OP_EQUAL = 0x87 -OP_EQUALVERIFY = 0x88 -OP_HASH160 = 0xa9 -OP_CHECKSIG = 0xac pubkey_prefix = (OP_DUP, OP_HASH160, 20) pubkey_suffix = (OP_EQUALVERIFY, OP_CHECKSIG) script_prefix = (OP_HASH160, 20) @@ -65,8 +60,10 @@ def is_valid(v): '''Check vector v for validity''' if len(set(v) - set(b58chars)) > 0: return False - result = b58decode_chk(v) - if result is None: + try: + payload, version = base58_to_byte(v) + result = bytes([version]) + payload + except ValueError: # thrown if checksum doesn't match return False for template in templates: prefix = bytearray(template[0]) @@ -83,7 +80,8 @@ def gen_valid_base58_vector(template): suffix = bytearray(template[2]) dst_prefix = bytearray(template[4]) dst_suffix = bytearray(template[5]) - rv = b58encode_chk(prefix + payload + suffix) + assert len(prefix) == 1 + rv = byte_to_base58(payload + suffix, prefix[0]) return rv, dst_prefix + payload + dst_suffix def gen_valid_vectors(): @@ -124,7 +122,8 @@ def gen_invalid_base58_vector(template): else: suffix = bytearray(template[2]) - val = b58encode_chk(prefix + payload + suffix) + assert len(prefix) == 1 + val = byte_to_base58(payload + suffix, prefix[0]) if random.randint(0,10)<1: # line corruption if randbool(): # add random character to end val += random.choice(b58chars) @@ -152,7 +151,6 @@ def gen_invalid_vectors(): yield val, if __name__ == '__main__': - import sys import json iters = {'valid':gen_valid_vectors, 'invalid':gen_invalid_vectors} try: diff --git a/doc/REST-interface.md b/doc/REST-interface.md index 2aa6f5ee8d45..5b25d76fc30f 100644 --- a/doc/REST-interface.md +++ b/doc/REST-interface.md @@ -47,18 +47,24 @@ The HTTP request and response are both handled entirely in-memory. With the /notxdetails/ option JSON response will only contain the transaction hash instead of the complete transaction details. The option only affects the JSON response. #### Blockheaders -`GET /rest/headers//.` +`GET /rest/headers/.?count=` Given a block hash: returns amount of blockheaders in upward direction. Returns empty if the block doesn't exist or it isn't in the active chain. +*Deprecated (but not removed) since 23.0:* +`GET /rest/headers//.` + #### Blockfilter Headers -`GET /rest/blockfilterheaders///.` +`GET /rest/blockfilterheaders//.?count=` Given a block hash: returns amount of blockfilter headers in upward direction for the filter type . Returns empty if the block doesn't exist or it isn't in the active chain. +*Deprecated (but not removed) since 23.0:* +`GET /rest/blockfilterheaders///.` + #### Blockfilters `GET /rest/blockfilter//.` diff --git a/doc/build-unix.md b/doc/build-unix.md index 90f31efbbff8..5c81e83dfc94 100644 --- a/doc/build-unix.md +++ b/doc/build-unix.md @@ -107,7 +107,7 @@ To build without GUI pass `--without-gui`. To build with Qt 5 you need the following: ```sh -sudo apt-get install libqt5gui5 libqt5core5a libqt5dbus5 qttools5-dev qttools5-dev-tools +sudo apt-get install qtbase5-dev qttools5-dev qttools5-dev-tools ``` Additionally, to support Wayland protocol for modern desktop environments: @@ -250,52 +250,6 @@ Otherwise, you can build Dash Core from self-compiled [depends](/depends/README. **Note**: You only need Berkeley DB if the wallet is enabled (see [*Disable-wallet mode*](#disable-wallet-mode)). -Security --------- -To help make your Dash Core installation more secure by making certain attacks impossible to -exploit even if a vulnerability is found, binaries are hardened by default. -This can be disabled with: - -Hardening Flags: - - ./configure --enable-hardening - ./configure --disable-hardening - - -Hardening enables the following features: -* _Position Independent Executable_: Build position independent code to take advantage of Address Space Layout Randomization - offered by some kernels. Attackers who can cause execution of code at an arbitrary memory - location are thwarted if they don't know where anything useful is located. - The stack and heap are randomly located by default, but this allows the code section to be - randomly located as well. - - On an AMD64 processor where a library was not compiled with -fPIC, this will cause an error - such as: "relocation R_X86_64_32 against `......' can not be used when making a shared object;" - - To test that you have built PIE executable, install scanelf, part of paxutils, and use: - - scanelf -e ./dashd - - The output should contain: - - TYPE - ET_DYN - -* _Non-executable Stack_: If the stack is executable then trivial stack-based buffer overflow exploits are possible if - vulnerable buffers are found. By default, Dash Core should be built with a non-executable stack, - but if one of the libraries it uses asks for an executable stack or someone makes a mistake - and uses a compiler extension which requires an executable stack, it will silently build an - executable without the non-executable stack protection. - - To verify that the stack is non-executable after compiling use: - `scanelf -e ./dashd` - - The output should contain: - STK/REL/PTL - RW- R-- RW- - - The STK RW- means that the stack is readable and writeable but not executable. - Disable-wallet mode -------------------- When the intention is to run only a P2P node without a wallet, Dash Core may be compiled in diff --git a/doc/developer-notes.md b/doc/developer-notes.md index 9824956fe908..5de6fa61e8ee 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -946,7 +946,9 @@ Threads and synchronization - Consistently use [Clang Thread Safety Analysis](https://clang.llvm.org/docs/ThreadSafetyAnalysis.html) annotations to get compile-time warnings about potential race conditions in code. Combine annotations in function declarations with - run-time asserts in function definitions: + run-time asserts in function definitions (`AssertLockNotHeld()` can be omitted if `LOCK()` is + called unconditionally after it because `LOCK()` does the same check as + `AssertLockNotHeld()` internally, for non-recursive mutexes): ```C++ // txmempool.h diff --git a/doc/reduce-memory.md b/doc/reduce-memory.md index 6b5ada7e2214..980c2b06ab9a 100644 --- a/doc/reduce-memory.md +++ b/doc/reduce-memory.md @@ -43,7 +43,7 @@ threads take up 8MiB for the thread stack on a 64-bit system, and 4MiB in a ## Linux specific -By default, since glibc `2.10`, the C library will create up to two heap arenas per core. This is known to cause excessive memory usage in some scenarios. To avoid this make a script that sets `MALLOC_ARENA_MAX` before starting dashd: +By default, glibc's implementation of `malloc` may use more than one arena. This is known to cause excessive memory usage in some scenarios. To avoid this, make a script that sets `MALLOC_ARENA_MAX` before starting dashd: ```bash #!/usr/bin/env bash diff --git a/doc/release-notes-24098.md b/doc/release-notes-24098.md new file mode 100644 index 000000000000..bc74ef655878 --- /dev/null +++ b/doc/release-notes-24098.md @@ -0,0 +1,20 @@ +Notable changes +=============== + +Updated REST APIs +----------------- + +- The `/headers/` and `/blockfilterheaders/` endpoints have been updated to use + a query parameter instead of path parameter to specify the result count. The + count parameter is now optional, and defaults to 5 for both endpoints. The old + endpoints are still functional, and have no documented behaviour change. + + For `/headers`, use + `GET /rest/headers/.?count=` + instead of + `GET /rest/headers//.` (deprecated) + + For `/blockfilterheaders/`, use + `GET /rest/blockfilterheaders//.?count=` + instead of + `GET /rest/blockfilterheaders///.` (deprecated) diff --git a/doc/release-notes-24629.md b/doc/release-notes-24629.md new file mode 100644 index 000000000000..36ccda440586 --- /dev/null +++ b/doc/release-notes-24629.md @@ -0,0 +1,7 @@ +Updated RPCs +------------ + +- The return value of the `pruneblockchain` method had an off-by-one bug, + returning the height of the block *after* the most recent pruned. This has + been corrected, and it now returns the height of the last pruned block as + documented. diff --git a/doc/release-notes-27068.md b/doc/release-notes-27068.md index 3f5c5dba37bd..d393c235609c 100644 --- a/doc/release-notes-27068.md +++ b/doc/release-notes-27068.md @@ -2,5 +2,6 @@ Wallet ------ - Wallet passphrases may now contain null characters. + Mnemonic passphrases may now contain null characters. Prior to this change, only characters up to the first - null character were recognized and accepted. (#27068) \ No newline at end of file + null character were recognized and accepted. (#6780 #6792) diff --git a/doc/release-notes-6711.md b/doc/release-notes-6711.md new file mode 100644 index 000000000000..b25545e2a84d --- /dev/null +++ b/doc/release-notes-6711.md @@ -0,0 +1,9 @@ +Updated settings +---------------- + +- BIP157 compact block filters are now automatically enabled for masternodes. This improves privacy for light clients + connecting to masternodes and enables better support for pruned nodes. When a node is configured as a masternode + (via `-masternodeblsprivkey`), both `-peerblockfilters` and `-blockfilterindex=basic` are automatically enabled. + Note that this feature requires approximately 1GB+ of additional disk space for the block filter index. + Regular nodes keep the previous defaults (disabled). Masternodes can still explicitly disable these features + if needed by setting `-peerblockfilters=0` or `-blockfilterindex=0` (#6711). diff --git a/doc/release-notes-6813.md b/doc/release-notes-6813.md new file mode 100644 index 000000000000..c8697813e73d --- /dev/null +++ b/doc/release-notes-6813.md @@ -0,0 +1,4 @@ +EvoDB migration +--------------- + +This release introduces a new internal format for masternode state data to support extended addresses and make future updates of this data seamless. Nodes will automatically migrate to the new format. Downgrading to an earlier version would require a full reindex. #6813 diff --git a/src/Makefile.am b/src/Makefile.am index 1b26de7005fc..ad292d263c00 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -73,6 +73,8 @@ LIBBITCOIN_WALLET_TOOL=libbitcoin_wallet_tool.a endif LIBBITCOIN_CRYPTO = $(LIBBITCOIN_CRYPTO_BASE) +LIBBITCOIN_CRYPTO_SPH = crypto/libbitcoin_crypto_sph.la +LIBBITCOIN_CRYPTO += $(LIBBITCOIN_CRYPTO_SPH) if ENABLE_SSE41 LIBBITCOIN_CRYPTO_SSE41 = crypto/libbitcoin_crypto_sse41.la LIBBITCOIN_CRYPTO += $(LIBBITCOIN_CRYPTO_SSE41) @@ -150,6 +152,9 @@ BITCOIN_CORE_H = \ cachemultimap.h \ blockfilter.h \ chain.h \ + chainlock/chainlock.h \ + chainlock/clsig.h \ + chainlock/signing.h \ chainparams.h \ chainparamsbase.h \ chainparamsseeds.h \ @@ -239,8 +244,6 @@ BITCOIN_CORE_H = \ key_io.h \ limitedmap.h \ llmq/blockprocessor.h \ - llmq/chainlocks.h \ - llmq/clsig.h \ llmq/commitment.h \ llmq/context.h \ llmq/debug.h \ @@ -302,6 +305,7 @@ BITCOIN_CORE_H = \ psbt.h \ random.h \ randomenv.h \ + rest.h \ rpc/blockchain.h \ rpc/client.h \ rpc/evo_util.h \ @@ -355,7 +359,6 @@ BITCOIN_CORE_H = \ util/enumerate.h \ util/epochguard.h \ util/error.h \ - util/expected.h \ util/fastrange.h \ util/fees.h \ util/golombrice.h \ @@ -434,7 +437,7 @@ BITCOIN_CORE_H = \ obj/build.h: FORCE @$(MKDIR_P) $(builddir)/obj - @$(top_srcdir)/share/genbuild.sh "$(abs_top_builddir)/src/obj/build.h" \ + $(AM_V_GEN) $(top_srcdir)/share/genbuild.sh "$(abs_top_builddir)/src/obj/build.h" \ "$(abs_top_srcdir)" libbitcoin_util_a-clientversion.$(OBJEXT): obj/build.h @@ -455,6 +458,9 @@ libbitcoin_node_a_SOURCES = \ blockencodings.cpp \ blockfilter.cpp \ chain.cpp \ + chainlock/chainlock.cpp \ + chainlock/clsig.cpp \ + chainlock/signing.cpp \ coinjoin/coinjoin.cpp \ coinjoin/context.cpp \ coinjoin/server.cpp \ @@ -498,8 +504,6 @@ libbitcoin_node_a_SOURCES = \ instantsend/lock.cpp \ instantsend/signing.cpp \ llmq/blockprocessor.cpp \ - llmq/chainlocks.cpp \ - llmq/clsig.cpp \ llmq/commitment.cpp \ llmq/context.cpp \ llmq/debug.cpp \ @@ -715,8 +719,16 @@ crypto_libbitcoin_crypto_avx2_la_CXXFLAGS += $(AVX2_CXXFLAGS) crypto_libbitcoin_crypto_avx2_la_CPPFLAGS += -DENABLE_AVX2 crypto_libbitcoin_crypto_avx2_la_SOURCES = crypto/sha256_avx2.cpp -# x11 -crypto_libbitcoin_crypto_base_la_SOURCES += \ +# See explanation for -static in crypto_libbitcoin_crypto_base_la's LDFLAGS and +# CXXFLAGS above +crypto_libbitcoin_crypto_sph_la_LDFLAGS = $(AM_LDFLAGS) -static +crypto_libbitcoin_crypto_sph_la_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) -static +crypto_libbitcoin_crypto_sph_la_CPPFLAGS = $(AM_CPPFLAGS) +crypto_libbitcoin_crypto_sph_la_CFLAGS = $(SPHLIB_CFLAGS) +crypto_libbitcoin_crypto_sph_la_CPPFLAGS += \ + -DSPH_SMALL_FOOTPRINT_CUBEHASH=1 \ + -DSPH_SMALL_FOOTPRINT_JH=1 +crypto_libbitcoin_crypto_sph_la_SOURCES = \ crypto/x11/aes_helper.c \ crypto/x11/blake.c \ crypto/x11/bmw.c \ @@ -1006,7 +1018,7 @@ endif # dashconsensus library # if BUILD_BITCOIN_LIBS include_HEADERS = script/bitcoinconsensus.h -libdashconsensus_la_SOURCES = support/cleanse.cpp $(crypto_libbitcoin_crypto_base_la_SOURCES) $(libbitcoin_consensus_a_SOURCES) +libdashconsensus_la_SOURCES = support/cleanse.cpp $(crypto_libbitcoin_crypto_base_la_SOURCES) $(crypto_libbitcoin_crypto_sph_la_SOURCES) $(libbitcoin_consensus_a_SOURCES) libdashconsensus_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined $(RELDFLAGS) libdashconsensus_la_LIBADD = $(LIBDASHBLS) $(LIBSECP256K1) $(GMP_LIBS) @@ -1071,7 +1083,7 @@ clean-local: -rm -rf *.dSYM test/*.dSYM bench/*.dSYM qt/*.dSYM qt/test/*.dSYM .rc.o: - @test -f $(WINDRES) + @test -f $(WINDRES) || (echo "windres $(WINDRES) not found, but is required to compile windows resource files"; exit 1) ## FIXME: How to get the appropriate modulename_CPPFLAGS in here? $(AM_V_GEN) $(WINDRES) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CPPFLAGS) -DWINDRES_PREPROC -i $< -o $@ @@ -1130,12 +1142,11 @@ endif %.raw.h: %.raw @$(MKDIR_P) $(@D) - @{ \ + $(AM_V_GEN) { \ echo "static unsigned const char $(*F)_raw[] = {" && \ $(HEXDUMP) -v -e '8/1 "0x%02x, "' -e '"\n"' $< | $(SED) -e 's/0x ,//g' && \ echo "};"; \ } > "$@.new" && mv -f "$@.new" "$@" - @echo "Generated $@" include Makefile.minisketch.include diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include index bc788ac810f8..1169d922984c 100644 --- a/src/Makefile.bench.include +++ b/src/Makefile.bench.include @@ -43,6 +43,7 @@ bench_bench_dash_SOURCES = \ bench/nanobench.cpp \ bench/peer_eviction.cpp \ bench/pool.cpp \ + bench/pow_hash.cpp \ bench/rpc_blockchain.cpp \ bench/rpc_mempool.cpp \ bench/strencodings.cpp \ @@ -88,6 +89,7 @@ if ENABLE_WALLET bench_bench_dash_SOURCES += bench/coin_selection.cpp bench_bench_dash_SOURCES += bench/wallet_balance.cpp bench_bench_dash_SOURCES += bench/wallet_create.cpp +bench_bench_dash_SOURCES += bench/wallet_loading.cpp bench_bench_dash_LDADD += $(BDB_LIBS) $(SQLITE_LIBS) endif diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index ae83c814f895..862b8ba505dc 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -448,13 +448,13 @@ translate: $(srcdir)/qt/dashstrings.cpp $(QT_FORMS_UI) $(QT_FORMS_UI) $(BITCOIN_ @rm -f $(srcdir)/qt/locale/dash_en.xlf.old $(QT_QRC_LOCALE_CPP): $(QT_QRC_LOCALE) $(QT_QM) - @test -f $(RCC) + @test -f $(RCC) || (echo "rcc $(RCC) not found, but is required for generating qrc cpp files"; exit 1) @cp -f $< $(@D)/temp_$( $@ @rm $(@D)/temp_$( $@ CLEAN_QT = $(nodist_qt_libbitcoinqt_a_SOURCES) $(QT_QM) $(QT_FORMS_H) qt/*.gcda qt/*.gcno qt/temp_dash_locale.qrc qt/res/css/colors/* @@ -467,7 +467,7 @@ dash_qt_clean: FORCE dash_qt : qt/dash-qt$(EXEEXT) ui_%.h: %.ui - @test -f $(UIC) + @test -f $(UIC) || (echo "uic $(UIC) not found, but is required for generating ui headers"; exit 1) @$(MKDIR_P) $(@D) $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(UIC) -o $@ $< || (echo "Error creating $@"; false) @@ -478,6 +478,6 @@ moc_%.cpp: %.h $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(MOC) $(DEFAULT_INCLUDES) $(QT_INCLUDES_UNSUPPRESSED) $(MOC_DEFS) $< > $@ %.qm: %.ts - @test -f $(LRELEASE) + @test -f $(LRELEASE) || (echo "lrelease $(LRELEASE) not found, but is required for generating translations"; exit 1) @$(MKDIR_P) $(@D) $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(LRELEASE) -silent $< -qm $@ diff --git a/src/Makefile.test.include b/src/Makefile.test.include index bed7081dd6d4..b05116eaee52 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -120,7 +120,12 @@ BITCOIN_TESTS =\ test/fs_tests.cpp \ test/getarg_tests.cpp \ test/governance_validators_tests.cpp \ + test/coinjoin_inouts_tests.cpp \ + test/coinjoin_dstxmanager_tests.cpp \ + test/coinjoin_basemanager_tests.cpp \ + test/coinjoin_queue_tests.cpp \ test/hash_tests.cpp \ + test/httpserver_tests.cpp \ test/i2p_tests.cpp \ test/interfaces_tests.cpp \ test/key_io_tests.cpp \ @@ -156,6 +161,8 @@ BITCOIN_TESTS =\ test/raii_event_tests.cpp \ test/random_tests.cpp \ test/ratecheck_tests.cpp \ + test/rest_tests.cpp \ + test/result_tests.cpp \ test/reverselock_tests.cpp \ test/rpc_tests.cpp \ test/sanity_tests.cpp \ @@ -208,6 +215,7 @@ BITCOIN_TESTS += \ wallet/test/wallet_crypto_tests.cpp \ wallet/test/wallet_transaction_tests.cpp \ wallet/test/coinselector_tests.cpp \ + wallet/test/availablecoins_tests.cpp \ wallet/test/init_tests.cpp \ wallet/test/ismine_tests.cpp \ wallet/test/scriptpubkeyman_tests.cpp @@ -222,6 +230,7 @@ BITCOIN_TESTS += wallet/test/db_tests.cpp endif FUZZ_WALLET_SRC = \ + wallet/test/fuzz/coincontrol.cpp \ wallet/test/fuzz/coinselection.cpp if USE_SQLITE @@ -363,6 +372,7 @@ test_fuzz_fuzz_SOURCES = \ test/fuzz/tx_in.cpp \ test/fuzz/tx_out.cpp \ test/fuzz/tx_pool.cpp \ + test/fuzz/txorphan.cpp \ test/fuzz/utxo_snapshot.cpp \ test/fuzz/validation_load_mempool.cpp \ test/fuzz/versionbits.cpp @@ -443,10 +453,9 @@ endif %.json.h: %.json @$(MKDIR_P) $(@D) - @{ \ + $(AM_V_GEN) { \ echo "namespace json_tests{" && \ echo "static unsigned const char $(*F)[] = {" && \ $(HEXDUMP) -v -e '8/1 "0x%02x, "' -e '"\n"' $< | $(SED) -e 's/0x ,//g' && \ echo "};};"; \ } > "$@.new" && mv -f "$@.new" "$@" - @echo "Generated $@" diff --git a/src/bench/coin_selection.cpp b/src/bench/coin_selection.cpp index 689524a716ea..7b44f5425bdc 100644 --- a/src/bench/coin_selection.cpp +++ b/src/bench/coin_selection.cpp @@ -54,10 +54,10 @@ static void CoinSelection(benchmark::Bench& bench) addCoin(3 * COIN, wallet, wtxs); // Create coins - std::vector coins; + wallet::CoinsResult available_coins; for (const auto& wtx : wtxs) { const auto txout = wtx->tx->vout.at(0); - coins.emplace_back(COutPoint(wtx->GetHash(), 0), txout, /*depth=*/6 * 24, CalculateMaximumSignedInputSize(txout, &wallet, /*coin_control=*/nullptr), /*spendable=*/true, /*solvable=*/true, /*safe=*/true, wtx->GetTxTime(), /*from_me=*/true, /*fees=*/ 0); + available_coins.legacy.emplace_back(COutPoint(wtx->GetHash(), 0), txout, /*depth=*/6 * 24, CalculateMaximumSignedInputSize(txout, &wallet, /*coin_control=*/nullptr), /*spendable=*/true, /*solvable=*/true, /*safe=*/true, wtx->GetTxTime(), /*from_me=*/true, /*fees=*/ 0); } const CoinEligibilityFilter filter_standard(1, 6, 0); FastRandomContext rand{}; @@ -73,7 +73,7 @@ static void CoinSelection(benchmark::Bench& bench) /*avoid_partial=*/ false, }; bench.run([&] { - auto result = AttemptSelection(wallet, 1003 * COIN, filter_standard, coins, coin_selection_params); + auto result = AttemptSelection(wallet, 1003 * COIN, filter_standard, available_coins, coin_selection_params, /*allow_mixed_output_types=*/true); assert(result); assert(result->GetSelectedValue() == 1003 * COIN); assert(result->GetInputSet().size() == 2); diff --git a/src/bench/crypto_hash.cpp b/src/bench/crypto_hash.cpp index d184bdc8bf8b..9db0703c6d1e 100644 --- a/src/bench/crypto_hash.cpp +++ b/src/bench/crypto_hash.cpp @@ -295,15 +295,6 @@ static void DSHA256_1M(benchmark::Bench& bench) }); } -static void X11_1M(benchmark::Bench& bench) -{ - uint256 hash; - std::vector in(BUFFER_SIZE,0); - bench.batch(in.size()).unit("byte").run([&] { - hash = HashX11(in.begin(), in.end()); - }); -} - /* Hash different number of bytes via DSHA256 */ static void DSHA256_0032b_single(benchmark::Bench& bench) { @@ -359,63 +350,7 @@ static void DSHA256_2048b_single(benchmark::Bench& bench) }); } -/* Hash different number of bytes via X11 */ -static void X11_0032b_single(benchmark::Bench& bench) -{ - uint256 hash; - std::vector in(32,0); - bench.batch(in.size()).unit("byte").run([&] { - hash = HashX11(in.begin(), in.end()); - }); -} - -static void X11_0080b_single(benchmark::Bench& bench) -{ - uint256 hash; - std::vector in(80,0); - bench.batch(in.size()).unit("byte").run([&] { - hash = HashX11(in.begin(), in.end()); - }); -} - -static void X11_0128b_single(benchmark::Bench& bench) -{ - uint256 hash; - std::vector in(128,0); - bench.batch(in.size()).unit("byte").run([&] { - hash = HashX11(in.begin(), in.end()); - }); -} - -static void X11_0512b_single(benchmark::Bench& bench) -{ - uint256 hash; - std::vector in(512,0); - bench.batch(in.size()).unit("byte").run([&] { - hash = HashX11(in.begin(), in.end()); - }); -} - -static void X11_1024b_single(benchmark::Bench& bench) -{ - uint256 hash; - std::vector in(1024,0); - bench.batch(in.size()).unit("byte").run([&] { - hash = HashX11(in.begin(), in.end()); - }); -} - -static void X11_2048b_single(benchmark::Bench& bench) -{ - uint256 hash; - std::vector in(2048,0); - bench.batch(in.size()).unit("byte").run([&] { - hash = HashX11(in.begin(), in.end()); - }); -} - BENCHMARK(DSHA256_1M); -BENCHMARK(X11_1M); BENCHMARK(DSHA256_0032b_single); BENCHMARK(DSHA256_0080b_single); @@ -423,10 +358,3 @@ BENCHMARK(DSHA256_0128b_single); BENCHMARK(DSHA256_0512b_single); BENCHMARK(DSHA256_1024b_single); BENCHMARK(DSHA256_2048b_single); - -BENCHMARK(X11_0032b_single); -BENCHMARK(X11_0080b_single); -BENCHMARK(X11_0128b_single); -BENCHMARK(X11_0512b_single); -BENCHMARK(X11_1024b_single); -BENCHMARK(X11_2048b_single); diff --git a/src/bench/pow_hash.cpp b/src/bench/pow_hash.cpp new file mode 100644 index 000000000000..d5f9c17f9808 --- /dev/null +++ b/src/bench/pow_hash.cpp @@ -0,0 +1,359 @@ +// Copyright (c) 2025 The Dash Core 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 + +namespace { +//! Bytes to hash per iteration +static constexpr size_t BUFFER_SIZE{1000*1000}; +//! Bytes required to represent 512-bit unsigned integers (uint512) +static constexpr size_t OUTPUT_SIZE{64}; + +inline void Pow_X11(benchmark::Bench& bench, const size_t bytes) +{ + uint256 hash{}; + std::vector in(bytes, 0); + bench.batch(in.size()).unit("byte").run([&] { + hash = HashX11(in.begin(), in.end()); + }); +} + +inline void Pow_Blake512(benchmark::Bench& bench, const size_t bytes) +{ + sph_blake512_context ctx; + uint8_t hash[OUTPUT_SIZE]; + std::vector in(bytes, 0); + bench.batch(in.size()).unit("byte").run([&] { + sph_blake512_init(&ctx); + sph_blake512(&ctx, in.data(), in.size()); + sph_blake512_close(&ctx, &hash); + }); +} + +inline void Pow_Bmw512(benchmark::Bench& bench, const size_t bytes) +{ + sph_bmw512_context ctx; + uint8_t hash[OUTPUT_SIZE]; + std::vector in(bytes, 0); + bench.batch(in.size()).unit("byte").run([&] { + sph_bmw512_init(&ctx); + sph_bmw512(&ctx, in.data(), in.size()); + sph_bmw512_close(&ctx, &hash); + }); +} + +inline void Pow_Cubehash512(benchmark::Bench& bench, const size_t bytes) +{ + sph_cubehash512_context ctx; + uint8_t hash[OUTPUT_SIZE]; + std::vector in(bytes, 0); + bench.batch(in.size()).unit("byte").run([&] { + sph_cubehash512_init(&ctx); + sph_cubehash512(&ctx, in.data(), in.size()); + sph_cubehash512_close(&ctx, &hash); + }); +} + +inline void Pow_Echo512(benchmark::Bench& bench, const size_t bytes) +{ + sph_echo512_context ctx; + uint8_t hash[OUTPUT_SIZE]; + std::vector in(bytes, 0); + bench.batch(in.size()).unit("byte").run([&] { + sph_echo512_init(&ctx); + sph_echo512(&ctx, in.data(), in.size()); + sph_echo512_close(&ctx, &hash); + }); +} + +inline void Pow_Groestl512(benchmark::Bench& bench, const size_t bytes) +{ + sph_groestl512_context ctx; + uint8_t hash[OUTPUT_SIZE]; + std::vector in(bytes, 0); + bench.batch(in.size()).unit("byte").run([&] { + sph_groestl512_init(&ctx); + sph_groestl512(&ctx, in.data(), in.size()); + sph_groestl512_close(&ctx, &hash); + }); +} + +inline void Pow_Jh512(benchmark::Bench& bench, const size_t bytes) +{ + sph_jh512_context ctx; + uint8_t hash[OUTPUT_SIZE]; + std::vector in(bytes, 0); + bench.batch(in.size()).unit("byte").run([&] { + sph_jh512_init(&ctx); + sph_jh512(&ctx, in.data(), in.size()); + sph_jh512_close(&ctx, &hash); + }); +} + +inline void Pow_Keccak512(benchmark::Bench& bench, const size_t bytes) +{ + sph_keccak512_context ctx; + uint8_t hash[OUTPUT_SIZE]; + std::vector in(bytes, 0); + bench.batch(in.size()).unit("byte").run([&] { + sph_keccak512_init(&ctx); + sph_keccak512(&ctx, in.data(), in.size()); + sph_keccak512_close(&ctx, &hash); + }); +} + +inline void Pow_Luffa512(benchmark::Bench& bench, const size_t bytes) +{ + sph_luffa512_context ctx; + uint8_t hash[OUTPUT_SIZE]; + std::vector in(bytes, 0); + bench.batch(in.size()).unit("byte").run([&] { + sph_luffa512_init(&ctx); + sph_luffa512(&ctx, in.data(), in.size()); + sph_luffa512_close(&ctx, &hash); + }); +} + +inline void Pow_Shavite512(benchmark::Bench& bench, const size_t bytes) +{ + sph_shavite512_context ctx; + uint8_t hash[OUTPUT_SIZE]; + std::vector in(bytes, 0); + bench.batch(in.size()).unit("byte").run([&] { + sph_shavite512_init(&ctx); + sph_shavite512(&ctx, in.data(), in.size()); + sph_shavite512_close(&ctx, &hash); + }); +} + +inline void Pow_Simd512(benchmark::Bench& bench, const size_t bytes) +{ + sph_simd512_context ctx; + uint8_t hash[OUTPUT_SIZE]; + std::vector in(bytes, 0); + bench.batch(in.size()).unit("byte").run([&] { + sph_simd512_init(&ctx); + sph_simd512(&ctx, in.data(), in.size()); + sph_simd512_close(&ctx, &hash); + }); +} + +inline void Pow_Skein512(benchmark::Bench& bench, const size_t bytes) +{ + sph_skein512_context ctx; + uint8_t hash[OUTPUT_SIZE]; + std::vector in(bytes, 0); + bench.batch(in.size()).unit("byte").run([&] { + sph_skein512_init(&ctx); + sph_skein512(&ctx, in.data(), in.size()); + sph_skein512_close(&ctx, &hash); + }); +} +} // anonymous namespace + +static void Pow_X11_0032b(benchmark::Bench& bench) { return Pow_X11(bench, 32); } +static void Pow_X11_0080b(benchmark::Bench& bench) { return Pow_X11(bench, 80); } +static void Pow_X11_0128b(benchmark::Bench& bench) { return Pow_X11(bench, 128); } +static void Pow_X11_0512b(benchmark::Bench& bench) { return Pow_X11(bench, 512); } +static void Pow_X11_1024b(benchmark::Bench& bench) { return Pow_X11(bench, 1024); } +static void Pow_X11_2048b(benchmark::Bench& bench) { return Pow_X11(bench, 2048); } +static void Pow_X11_1M(benchmark::Bench& bench) { return Pow_X11(bench, BUFFER_SIZE); } + +static void Pow_Blake512_0032b(benchmark::Bench& bench) { return Pow_Blake512(bench, 32); } +static void Pow_Blake512_0080b(benchmark::Bench& bench) { return Pow_Blake512(bench, 80); } +static void Pow_Blake512_0128b(benchmark::Bench& bench) { return Pow_Blake512(bench, 128); } +static void Pow_Blake512_0512b(benchmark::Bench& bench) { return Pow_Blake512(bench, 512); } +static void Pow_Blake512_1024b(benchmark::Bench& bench) { return Pow_Blake512(bench, 1024); } +static void Pow_Blake512_2048b(benchmark::Bench& bench) { return Pow_Blake512(bench, 2048); } +static void Pow_Blake512_1M(benchmark::Bench& bench) { return Pow_Blake512(bench, BUFFER_SIZE); } + +static void Pow_Bmw512_0032b(benchmark::Bench& bench) { return Pow_Bmw512(bench, 32); } +static void Pow_Bmw512_0080b(benchmark::Bench& bench) { return Pow_Bmw512(bench, 80); } +static void Pow_Bmw512_0128b(benchmark::Bench& bench) { return Pow_Bmw512(bench, 128); } +static void Pow_Bmw512_0512b(benchmark::Bench& bench) { return Pow_Bmw512(bench, 512); } +static void Pow_Bmw512_1024b(benchmark::Bench& bench) { return Pow_Bmw512(bench, 1024); } +static void Pow_Bmw512_2048b(benchmark::Bench& bench) { return Pow_Bmw512(bench, 2048); } +static void Pow_Bmw512_1M(benchmark::Bench& bench) { return Pow_Bmw512(bench, BUFFER_SIZE); } + +static void Pow_Cubehash512_0032b(benchmark::Bench& bench) { return Pow_Cubehash512(bench, 32); } +static void Pow_Cubehash512_0080b(benchmark::Bench& bench) { return Pow_Cubehash512(bench, 80); } +static void Pow_Cubehash512_0128b(benchmark::Bench& bench) { return Pow_Cubehash512(bench, 128); } +static void Pow_Cubehash512_0512b(benchmark::Bench& bench) { return Pow_Cubehash512(bench, 512); } +static void Pow_Cubehash512_1024b(benchmark::Bench& bench) { return Pow_Cubehash512(bench, 1024); } +static void Pow_Cubehash512_2048b(benchmark::Bench& bench) { return Pow_Cubehash512(bench, 2048); } +static void Pow_Cubehash512_1M(benchmark::Bench& bench) { return Pow_Cubehash512(bench, BUFFER_SIZE); } + +static void Pow_Echo512_0032b(benchmark::Bench& bench) { return Pow_Echo512(bench, 32); } +static void Pow_Echo512_0080b(benchmark::Bench& bench) { return Pow_Echo512(bench, 80); } +static void Pow_Echo512_0128b(benchmark::Bench& bench) { return Pow_Echo512(bench, 128); } +static void Pow_Echo512_0512b(benchmark::Bench& bench) { return Pow_Echo512(bench, 512); } +static void Pow_Echo512_1024b(benchmark::Bench& bench) { return Pow_Echo512(bench, 1024); } +static void Pow_Echo512_2048b(benchmark::Bench& bench) { return Pow_Echo512(bench, 2048); } +static void Pow_Echo512_1M(benchmark::Bench& bench) { return Pow_Echo512(bench, BUFFER_SIZE); } + +static void Pow_Groestl512_0032b(benchmark::Bench& bench) { return Pow_Groestl512(bench, 32); } +static void Pow_Groestl512_0080b(benchmark::Bench& bench) { return Pow_Groestl512(bench, 80); } +static void Pow_Groestl512_0128b(benchmark::Bench& bench) { return Pow_Groestl512(bench, 128); } +static void Pow_Groestl512_0512b(benchmark::Bench& bench) { return Pow_Groestl512(bench, 512); } +static void Pow_Groestl512_1024b(benchmark::Bench& bench) { return Pow_Groestl512(bench, 1024); } +static void Pow_Groestl512_2048b(benchmark::Bench& bench) { return Pow_Groestl512(bench, 2048); } +static void Pow_Groestl512_1M(benchmark::Bench& bench) { return Pow_Groestl512(bench, BUFFER_SIZE); } + +static void Pow_Jh512_0032b(benchmark::Bench& bench) { return Pow_Jh512(bench, 32); } +static void Pow_Jh512_0080b(benchmark::Bench& bench) { return Pow_Jh512(bench, 80); } +static void Pow_Jh512_0128b(benchmark::Bench& bench) { return Pow_Jh512(bench, 128); } +static void Pow_Jh512_0512b(benchmark::Bench& bench) { return Pow_Jh512(bench, 512); } +static void Pow_Jh512_1024b(benchmark::Bench& bench) { return Pow_Jh512(bench, 1024); } +static void Pow_Jh512_2048b(benchmark::Bench& bench) { return Pow_Jh512(bench, 2048); } +static void Pow_Jh512_1M(benchmark::Bench& bench) { return Pow_Jh512(bench, BUFFER_SIZE); } + +static void Pow_Keccak512_0032b(benchmark::Bench& bench) { return Pow_Keccak512(bench, 32); } +static void Pow_Keccak512_0080b(benchmark::Bench& bench) { return Pow_Keccak512(bench, 80); } +static void Pow_Keccak512_0128b(benchmark::Bench& bench) { return Pow_Keccak512(bench, 128); } +static void Pow_Keccak512_0512b(benchmark::Bench& bench) { return Pow_Keccak512(bench, 512); } +static void Pow_Keccak512_1024b(benchmark::Bench& bench) { return Pow_Keccak512(bench, 1024); } +static void Pow_Keccak512_2048b(benchmark::Bench& bench) { return Pow_Keccak512(bench, 2048); } +static void Pow_Keccak512_1M(benchmark::Bench& bench) { return Pow_Keccak512(bench, BUFFER_SIZE); } + +static void Pow_Luffa512_0032b(benchmark::Bench& bench) { return Pow_Luffa512(bench, 32); } +static void Pow_Luffa512_0080b(benchmark::Bench& bench) { return Pow_Luffa512(bench, 80); } +static void Pow_Luffa512_0128b(benchmark::Bench& bench) { return Pow_Luffa512(bench, 128); } +static void Pow_Luffa512_0512b(benchmark::Bench& bench) { return Pow_Luffa512(bench, 512); } +static void Pow_Luffa512_1024b(benchmark::Bench& bench) { return Pow_Luffa512(bench, 1024); } +static void Pow_Luffa512_2048b(benchmark::Bench& bench) { return Pow_Luffa512(bench, 2048); } +static void Pow_Luffa512_1M(benchmark::Bench& bench) { return Pow_Luffa512(bench, BUFFER_SIZE); } + +static void Pow_Shavite512_0032b(benchmark::Bench& bench) { return Pow_Shavite512(bench, 32); } +static void Pow_Shavite512_0080b(benchmark::Bench& bench) { return Pow_Shavite512(bench, 80); } +static void Pow_Shavite512_0128b(benchmark::Bench& bench) { return Pow_Shavite512(bench, 128); } +static void Pow_Shavite512_0512b(benchmark::Bench& bench) { return Pow_Shavite512(bench, 512); } +static void Pow_Shavite512_1024b(benchmark::Bench& bench) { return Pow_Shavite512(bench, 1024); } +static void Pow_Shavite512_2048b(benchmark::Bench& bench) { return Pow_Shavite512(bench, 2048); } +static void Pow_Shavite512_1M(benchmark::Bench& bench) { return Pow_Shavite512(bench, BUFFER_SIZE); } + +static void Pow_Simd512_0032b(benchmark::Bench& bench) { return Pow_Simd512(bench, 32); } +static void Pow_Simd512_0080b(benchmark::Bench& bench) { return Pow_Simd512(bench, 80); } +static void Pow_Simd512_0128b(benchmark::Bench& bench) { return Pow_Simd512(bench, 128); } +static void Pow_Simd512_0512b(benchmark::Bench& bench) { return Pow_Simd512(bench, 512); } +static void Pow_Simd512_1024b(benchmark::Bench& bench) { return Pow_Simd512(bench, 1024); } +static void Pow_Simd512_2048b(benchmark::Bench& bench) { return Pow_Simd512(bench, 2048); } +static void Pow_Simd512_1M(benchmark::Bench& bench) { return Pow_Simd512(bench, BUFFER_SIZE); } + +static void Pow_Skein512_0032b(benchmark::Bench& bench) { return Pow_Skein512(bench, 32); } +static void Pow_Skein512_0080b(benchmark::Bench& bench) { return Pow_Skein512(bench, 80); } +static void Pow_Skein512_0128b(benchmark::Bench& bench) { return Pow_Skein512(bench, 128); } +static void Pow_Skein512_0512b(benchmark::Bench& bench) { return Pow_Skein512(bench, 512); } +static void Pow_Skein512_1024b(benchmark::Bench& bench) { return Pow_Skein512(bench, 1024); } +static void Pow_Skein512_2048b(benchmark::Bench& bench) { return Pow_Skein512(bench, 2048); } +static void Pow_Skein512_1M(benchmark::Bench& bench) { return Pow_Skein512(bench, BUFFER_SIZE); } + +BENCHMARK(Pow_X11_0032b); +BENCHMARK(Pow_X11_0080b); +BENCHMARK(Pow_X11_0128b); +BENCHMARK(Pow_X11_0512b); +BENCHMARK(Pow_X11_1024b); +BENCHMARK(Pow_X11_2048b); +BENCHMARK(Pow_X11_1M); + +BENCHMARK(Pow_Blake512_0032b); +BENCHMARK(Pow_Blake512_0080b); +BENCHMARK(Pow_Blake512_0128b); +BENCHMARK(Pow_Blake512_0512b); +BENCHMARK(Pow_Blake512_1024b); +BENCHMARK(Pow_Blake512_2048b); +BENCHMARK(Pow_Blake512_1M); + +BENCHMARK(Pow_Bmw512_0032b); +BENCHMARK(Pow_Bmw512_0080b); +BENCHMARK(Pow_Bmw512_0128b); +BENCHMARK(Pow_Bmw512_0512b); +BENCHMARK(Pow_Bmw512_1024b); +BENCHMARK(Pow_Bmw512_2048b); +BENCHMARK(Pow_Bmw512_1M); + +BENCHMARK(Pow_Cubehash512_0032b); +BENCHMARK(Pow_Cubehash512_0080b); +BENCHMARK(Pow_Cubehash512_0128b); +BENCHMARK(Pow_Cubehash512_0512b); +BENCHMARK(Pow_Cubehash512_1024b); +BENCHMARK(Pow_Cubehash512_2048b); +BENCHMARK(Pow_Cubehash512_1M); + +BENCHMARK(Pow_Echo512_0032b); +BENCHMARK(Pow_Echo512_0080b); +BENCHMARK(Pow_Echo512_0128b); +BENCHMARK(Pow_Echo512_0512b); +BENCHMARK(Pow_Echo512_1024b); +BENCHMARK(Pow_Echo512_2048b); +BENCHMARK(Pow_Echo512_1M); + +BENCHMARK(Pow_Groestl512_0032b); +BENCHMARK(Pow_Groestl512_0080b); +BENCHMARK(Pow_Groestl512_0128b); +BENCHMARK(Pow_Groestl512_0512b); +BENCHMARK(Pow_Groestl512_1024b); +BENCHMARK(Pow_Groestl512_2048b); +BENCHMARK(Pow_Groestl512_1M); + +BENCHMARK(Pow_Jh512_0032b); +BENCHMARK(Pow_Jh512_0080b); +BENCHMARK(Pow_Jh512_0128b); +BENCHMARK(Pow_Jh512_0512b); +BENCHMARK(Pow_Jh512_1024b); +BENCHMARK(Pow_Jh512_2048b); +BENCHMARK(Pow_Jh512_1M); + +BENCHMARK(Pow_Keccak512_0032b); +BENCHMARK(Pow_Keccak512_0080b); +BENCHMARK(Pow_Keccak512_0128b); +BENCHMARK(Pow_Keccak512_0512b); +BENCHMARK(Pow_Keccak512_1024b); +BENCHMARK(Pow_Keccak512_2048b); +BENCHMARK(Pow_Keccak512_1M); + +BENCHMARK(Pow_Luffa512_0032b); +BENCHMARK(Pow_Luffa512_0080b); +BENCHMARK(Pow_Luffa512_0128b); +BENCHMARK(Pow_Luffa512_0512b); +BENCHMARK(Pow_Luffa512_1024b); +BENCHMARK(Pow_Luffa512_2048b); +BENCHMARK(Pow_Luffa512_1M); + +BENCHMARK(Pow_Shavite512_0032b); +BENCHMARK(Pow_Shavite512_0080b); +BENCHMARK(Pow_Shavite512_0128b); +BENCHMARK(Pow_Shavite512_0512b); +BENCHMARK(Pow_Shavite512_1024b); +BENCHMARK(Pow_Shavite512_2048b); +BENCHMARK(Pow_Shavite512_1M); + +BENCHMARK(Pow_Simd512_0032b); +BENCHMARK(Pow_Simd512_0080b); +BENCHMARK(Pow_Simd512_0128b); +BENCHMARK(Pow_Simd512_0512b); +BENCHMARK(Pow_Simd512_1024b); +BENCHMARK(Pow_Simd512_2048b); +BENCHMARK(Pow_Simd512_1M); + +BENCHMARK(Pow_Skein512_0032b); +BENCHMARK(Pow_Skein512_0080b); +BENCHMARK(Pow_Skein512_0128b); +BENCHMARK(Pow_Skein512_0512b); +BENCHMARK(Pow_Skein512_1024b); +BENCHMARK(Pow_Skein512_2048b); +BENCHMARK(Pow_Skein512_1M); diff --git a/src/bench/rpc_blockchain.cpp b/src/bench/rpc_blockchain.cpp index 33fc11065d89..9ed1fffb2f78 100644 --- a/src/bench/rpc_blockchain.cpp +++ b/src/bench/rpc_blockchain.cpp @@ -5,9 +5,9 @@ #include #include +#include #include #include -#include #include #include #include diff --git a/src/bench/util_time.cpp b/src/bench/util_time.cpp index afc733482e8a..c45584988d9a 100644 --- a/src/bench/util_time.cpp +++ b/src/bench/util_time.cpp @@ -32,7 +32,7 @@ static void BenchTimeMillis(benchmark::Bench& bench) static void BenchTimeMillisSys(benchmark::Bench& bench) { bench.run([&] { - (void)GetTimeMillis(); + (void)TicksSinceEpoch(SystemClock::now()); }); } diff --git a/src/bench/wallet_loading.cpp b/src/bench/wallet_loading.cpp new file mode 100644 index 000000000000..b01732b615a1 --- /dev/null +++ b/src/bench/wallet_loading.cpp @@ -0,0 +1,129 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using wallet::CWallet; +using wallet::DatabaseFormat; +using wallet::DatabaseOptions; +using wallet::ISMINE_SPENDABLE; +using wallet::MakeWalletDatabase; +using wallet::TxStateInactive; +using wallet::WALLET_FLAG_DESCRIPTORS; +using wallet::WalletContext; +using wallet::WalletDatabase; + +static const std::shared_ptr BenchLoadWallet(std::unique_ptr database, WalletContext& context, DatabaseOptions& options) +{ + bilingual_str error; + std::vector warnings; + auto wallet = CWallet::Create(context, "", std::move(database), options.create_flags, error, warnings); + NotifyWalletLoaded(context, wallet); + if (context.chain) { + wallet->postInitProcess(); + } + return wallet; +} + +static void BenchUnloadWallet(std::shared_ptr&& wallet) +{ + SyncWithValidationInterfaceQueue(); + wallet->m_chain_notifications_handler.reset(); + UnloadWallet(std::move(wallet)); +} + +static void AddTx(CWallet& wallet) +{ + CMutableTransaction mtx; + mtx.vout.push_back({COIN, GetScriptForDestination(*Assert(wallet.GetNewDestination("")))}); + mtx.vin.push_back(CTxIn()); + + wallet.AddToWallet(MakeTransactionRef(mtx), TxStateInactive{}); +} + +static std::unique_ptr DuplicateMockDatabase(WalletDatabase& database, DatabaseOptions& options) +{ + auto new_database = CreateMockWalletDatabase(options); + + // Get a cursor to the original database + auto batch = database.MakeBatch(); + batch->StartCursor(); + + // Get a batch for the new database + auto new_batch = new_database->MakeBatch(); + + // Read all records from the original database and write them to the new one + while (true) { + CDataStream key(SER_DISK, CLIENT_VERSION); + CDataStream value(SER_DISK, CLIENT_VERSION); + bool complete; + batch->ReadAtCursor(key, value, complete); + if (complete) break; + new_batch->Write(key, value); + } + + return new_database; +} + +static void WalletLoading(benchmark::Bench& bench, bool legacy_wallet) +{ + const auto test_setup = MakeNoLogFileContext(); + test_setup->m_args.ForceSetArg("-unsafesqlitesync", "1"); + + WalletContext context; + context.args = &test_setup->m_args; + context.chain = test_setup->m_node.chain.get(); + + // Setup the wallet + // Loading the wallet will also create it + DatabaseOptions options; + if (legacy_wallet) { + options.require_format = DatabaseFormat::BERKELEY; + } else { + options.create_flags = WALLET_FLAG_DESCRIPTORS; + options.require_format = DatabaseFormat::SQLITE; + } + auto database = CreateMockWalletDatabase(options); + auto wallet = BenchLoadWallet(std::move(database), context, options); + + // Generate a bunch of transactions and addresses to put into the wallet + for (int i = 0; i < 1000; ++i) { + AddTx(*wallet); + } + + database = DuplicateMockDatabase(wallet->GetDatabase(), options); + + // reload the wallet for the actual benchmark + BenchUnloadWallet(std::move(wallet)); + + bench.epochs(5).run([&] { + wallet = BenchLoadWallet(std::move(database), context, options); + + // Cleanup + database = DuplicateMockDatabase(wallet->GetDatabase(), options); + BenchUnloadWallet(std::move(wallet)); + }); +} + +#ifdef USE_BDB +static void WalletLoadingLegacy(benchmark::Bench& bench) { WalletLoading(bench, /*legacy_wallet=*/true); } +BENCHMARK(WalletLoadingLegacy); +#endif + +#ifdef USE_SQLITE +static void WalletLoadingDescriptors(benchmark::Bench& bench) { WalletLoading(bench, /*legacy_wallet=*/false); } +BENCHMARK(WalletLoadingDescriptors); +#endif diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 430ebb9257b6..ac548a4b8613 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -828,7 +828,10 @@ static UniValue CallRPC(BaseRequestHandler* rh, const std::string& strMethod, co if (response.error != -1) { responseErrorMessage = strprintf(" (error code %d - \"%s\")", response.error, http_errorstring(response.error)); } - throw CConnectionFailed(strprintf("Could not connect to the server %s:%d%s\n\nMake sure the dashd server is running and that you are connecting to the correct RPC port.", host, port, responseErrorMessage)); + throw CConnectionFailed(strprintf("Could not connect to the server %s:%d%s\n\n" + "Make sure the dashd server is running and that you are connecting to the correct RPC port.\n" + "Use \"dash-cli -help\" for more info.", + host, port, responseErrorMessage)); } else if (response.status == HTTP_UNAUTHORIZED) { if (failedToGetAuthCookie) { throw std::runtime_error(strprintf( diff --git a/src/chain.cpp b/src/chain.cpp index 2480047d024f..765c4d55a6ba 100644 --- a/src/chain.cpp +++ b/src/chain.cpp @@ -19,11 +19,9 @@ std::string CBlockIndex::ToString() const pprev, nHeight, hashMerkleRoot.ToString(), GetBlockHash().ToString()); } -void CChain::SetTip(CBlockIndex *pindex) { - if (pindex == nullptr) { - vChain.clear(); - return; - } +void CChain::SetTip(CBlockIndex& block) +{ + CBlockIndex* pindex = █ vChain.resize(pindex->nHeight + 1); while (pindex && vChain[pindex->nHeight] != pindex) { vChain[pindex->nHeight] = pindex; diff --git a/src/chain.h b/src/chain.h index f7fe7584936b..2fdac98e85c0 100644 --- a/src/chain.h +++ b/src/chain.h @@ -470,7 +470,7 @@ class CChain } /** Set/initialize a chain with a given tip. */ - void SetTip(CBlockIndex* pindex); + void SetTip(CBlockIndex& block); /** Return a CBlockLocator that refers to a block in this chain (by default the tip). */ CBlockLocator GetLocator(const CBlockIndex* pindex = nullptr) const; diff --git a/src/chainlock/chainlock.cpp b/src/chainlock/chainlock.cpp new file mode 100644 index 000000000000..15e235dea093 --- /dev/null +++ b/src/chainlock/chainlock.cpp @@ -0,0 +1,490 @@ +// Copyright (c) 2019-2025 The Dash Core developers +// Distributed under the MIT/X11 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 + +// Forward declaration to break dependency over node/transaction.h +namespace node { +CTransactionRef GetTransaction(const CBlockIndex* const block_index, const CTxMemPool* const mempool, + const uint256& hash, const Consensus::Params& consensusParams, uint256& hashBlock); +} // namespace node + +using node::GetTransaction; + +namespace llmq { +namespace { +static constexpr auto CLEANUP_INTERVAL{30s}; +static constexpr auto CLEANUP_SEEN_TIMEOUT{24h}; +//! How long to wait for islocks until we consider a block with non-islocked TXs to be safe to sign +static constexpr auto WAIT_FOR_ISLOCK_TIMEOUT{10min}; +} // anonymous namespace + +bool AreChainLocksEnabled(const CSporkManager& sporkman) +{ + return sporkman.IsSporkActive(SPORK_19_CHAINLOCKS_ENABLED); +} + +CChainLocksHandler::CChainLocksHandler(CChainState& chainstate, CQuorumManager& _qman, CSigningManager& _sigman, + CSigSharesManager& _shareman, CSporkManager& sporkman, CTxMemPool& _mempool, + const CMasternodeSync& mn_sync, bool is_masternode) : + m_chainstate{chainstate}, + qman{_qman}, + spork_manager{sporkman}, + mempool{_mempool}, + m_mn_sync{mn_sync}, + scheduler{std::make_unique()}, + scheduler_thread{ + std::make_unique(std::thread(util::TraceThread, "cl-schdlr", [&] { scheduler->serviceQueue(); }))}, + m_signer{is_masternode + ? std::make_unique(chainstate, *this, _sigman, _shareman, sporkman, mn_sync) + : nullptr} +{ +} + +CChainLocksHandler::~CChainLocksHandler() +{ + scheduler->stop(); + scheduler_thread->join(); +} + +void CChainLocksHandler::Start(const llmq::CInstantSendManager& isman) +{ + if (m_signer) { + m_signer->Start(); + } + scheduler->scheduleEvery( + [&]() { + CheckActiveState(); + EnforceBestChainLock(); + Cleanup(); + // regularly retry signing the current chaintip as it might have failed before due to missing islocks + if (m_signer) { + m_signer->TrySignChainTip(isman); + } + }, + std::chrono::seconds{5}); +} + +void CChainLocksHandler::Stop() +{ + scheduler->stop(); + if (m_signer) { + m_signer->Stop(); + } +} + +bool CChainLocksHandler::AlreadyHave(const CInv& inv) const +{ + LOCK(cs); + return seenChainLocks.count(inv.hash) != 0; +} + +bool CChainLocksHandler::GetChainLockByHash(const uint256& hash, chainlock::ChainLockSig& ret) const +{ + LOCK(cs); + + if (hash != bestChainLockHash) { + // we only propagate the best one and ditch all the old ones + return false; + } + + ret = bestChainLock; + return true; +} + +chainlock::ChainLockSig CChainLocksHandler::GetBestChainLock() const +{ + LOCK(cs); + return bestChainLock; +} + +void CChainLocksHandler::UpdateTxFirstSeenMap(const std::unordered_set& tx, const int64_t& time) +{ + AssertLockNotHeld(cs); + LOCK(cs); + for (const auto& txid : tx) { + txFirstSeenTime.emplace(txid, time); + } +} + +MessageProcessingResult CChainLocksHandler::ProcessNewChainLock(const NodeId from, const chainlock::ChainLockSig& clsig, + const uint256& hash) +{ + CheckActiveState(); + + { + LOCK(cs); + if (!seenChainLocks.emplace(hash, GetTime()).second) { + return {}; + } + + if (!bestChainLock.IsNull() && clsig.getHeight() <= bestChainLock.getHeight()) { + // no need to process/relay older CLSIGs + return {}; + } + } + + if (const auto ret = VerifyChainLock(clsig); ret != VerifyRecSigStatus::Valid) { + LogPrint(BCLog::CHAINLOCKS, "CChainLocksHandler::%s -- invalid CLSIG (%s), status=%d peer=%d\n", __func__, + clsig.ToString(), ToUnderlying(ret), from); + if (from != -1) { + return MisbehavingError{10}; + } + return {}; + } + + const CBlockIndex* pindex = WITH_LOCK(::cs_main, return m_chainstate.m_blockman.LookupBlockIndex(clsig.getBlockHash())); + const CInv clsig_inv(MSG_CLSIG, hash); + + { + LOCK(cs); + bestChainLockHash = hash; + bestChainLock = clsig; + + if (pindex) { + if (pindex->nHeight != clsig.getHeight()) { + // Should not happen, same as the conflict check from above. + LogPrintf("CChainLocksHandler::%s -- height of CLSIG (%s) does not match the specified block's height (%d)\n", + __func__, clsig.ToString(), pindex->nHeight); + // Note: not relaying clsig here + return {}; + } + bestChainLockWithKnownBlock = bestChainLock; + bestChainLockBlockIndex = pindex; + } else { + // We don't know the block/header for this CLSIG yet, so bail out for now and when the + // block/header later comes in, we will enforce the correct chain. We still relay further. + return clsig_inv; + } + } + + scheduler->scheduleFromNow( + [&]() { + CheckActiveState(); + EnforceBestChainLock(); + }, + std::chrono::seconds{0}); + + LogPrint(BCLog::CHAINLOCKS, "CChainLocksHandler::%s -- processed new CLSIG (%s), peer=%d\n", __func__, + clsig.ToString(), from); + + return clsig_inv; +} + +void CChainLocksHandler::AcceptedBlockHeader(gsl::not_null pindexNew) +{ + LOCK(cs); + + if (pindexNew->GetBlockHash() == bestChainLock.getBlockHash()) { + LogPrint(BCLog::CHAINLOCKS, "CChainLocksHandler::%s -- block header %s came in late, updating and enforcing\n", + __func__, pindexNew->GetBlockHash().ToString()); + + if (bestChainLock.getHeight() != pindexNew->nHeight) { + // Should not happen, same as the conflict check from ProcessNewChainLock. + LogPrintf("CChainLocksHandler::%s -- height of CLSIG (%s) does not match the specified block's height (%d)\n", + __func__, bestChainLock.ToString(), pindexNew->nHeight); + return; + } + + // when EnforceBestChainLock is called later, it might end up invalidating other chains but not activating the + // CLSIG locked chain. This happens when only the header is known but the block is still missing yet. The usual + // block processing logic will handle this when the block arrives + bestChainLockWithKnownBlock = bestChainLock; + bestChainLockBlockIndex = pindexNew; + } +} + +void CChainLocksHandler::UpdatedBlockTip(const llmq::CInstantSendManager& isman) +{ + // don't call TrySignChainTip directly but instead let the scheduler call it. This way we ensure that cs_main is + // never locked and TrySignChainTip is not called twice in parallel. Also avoids recursive calls due to + // EnforceBestChainLock switching chains. + // atomic[If tryLockChainTipScheduled is false, do (set it to true] and schedule signing). + if (bool expected = false; tryLockChainTipScheduled.compare_exchange_strong(expected, true)) { + scheduler->scheduleFromNow( + [&]() { + CheckActiveState(); + EnforceBestChainLock(); + Cleanup(); + if (m_signer) { + m_signer->TrySignChainTip(isman); + } + tryLockChainTipScheduled = false; + }, + std::chrono::seconds{0}); + } +} + +void CChainLocksHandler::CheckActiveState() +{ + bool oldIsEnabled = isEnabled; + isEnabled = AreChainLocksEnabled(spork_manager); + + if (!oldIsEnabled && isEnabled) { + // ChainLocks got activated just recently, but it's possible that it was already running before, leaving + // us with some stale values which we should not try to enforce anymore (there probably was a good reason + // to disable spork19) + LOCK(cs); + bestChainLockHash = uint256(); + bestChainLock = bestChainLockWithKnownBlock = chainlock::ChainLockSig(); + bestChainLockBlockIndex = lastNotifyChainLockBlockIndex = nullptr; + } +} + +void CChainLocksHandler::TransactionAddedToMempool(const CTransactionRef& tx, int64_t nAcceptTime) +{ + if (tx->IsCoinBase() || tx->vin.empty()) { + return; + } + + LOCK(cs); + txFirstSeenTime.emplace(tx->GetHash(), nAcceptTime); +} + +void CChainLocksHandler::BlockConnected(const std::shared_ptr& pblock, gsl::not_null pindex) +{ + if (!m_mn_sync.IsBlockchainSynced()) { + return; + } + + // We listen for BlockConnected so that we can collect all TX ids of all included TXs of newly received blocks + int64_t curTime = GetTime().count(); + { + LOCK(cs); + for (const auto& tx : pblock->vtx) { + if (!tx->IsCoinBase() && !tx->vin.empty()) { + txFirstSeenTime.emplace(tx->GetHash(), curTime); + } + } + } + + // We need this information later when we try to sign a new tip, so that we can determine if all included TXs are safe. + if (m_signer) { + m_signer->UpdateBlockHashTxidMap(pindex->GetBlockHash(), pblock->vtx); + } +} + +void CChainLocksHandler::BlockDisconnected(const std::shared_ptr& pblock, + gsl::not_null pindexDisconnected) +{ + if (m_signer) { + m_signer->EraseFromBlockHashTxidMap(pindexDisconnected->GetBlockHash()); + } +} + +int32_t CChainLocksHandler::GetBestChainLockHeight() const +{ + AssertLockNotHeld(cs); + LOCK(cs); + return bestChainLock.getHeight(); +} + +bool CChainLocksHandler::IsTxSafeForMining(const uint256& txid) const +{ + auto tx_age{0s}; + { + LOCK(cs); + auto it = txFirstSeenTime.find(txid); + if (it != txFirstSeenTime.end()) { + tx_age = GetTime() - it->second; + } + } + + return tx_age >= WAIT_FOR_ISLOCK_TIMEOUT; +} + +// WARNING: cs_main and cs should not be held! +// This should also not be called from validation signals, as this might result in recursive calls +void CChainLocksHandler::EnforceBestChainLock() +{ + AssertLockNotHeld(cs); + AssertLockNotHeld(cs_main); + + std::shared_ptr clsig; + const CBlockIndex* pindex; + const CBlockIndex* currentBestChainLockBlockIndex; + { + LOCK(cs); + + if (!IsEnabled()) { + return; + } + + clsig = std::make_shared(bestChainLockWithKnownBlock); + pindex = currentBestChainLockBlockIndex = this->bestChainLockBlockIndex; + + if (currentBestChainLockBlockIndex == nullptr) { + // we don't have the header/block, so we can't do anything right now + return; + } + } + + BlockValidationState dummy_state; + + // Go backwards through the chain referenced by clsig until we find a block that is part of the main chain. + // For each of these blocks, check if there are children that are NOT part of the chain referenced by clsig + // and mark all of them as conflicting. + LogPrint(BCLog::CHAINLOCKS, "CChainLocksHandler::%s -- enforcing block %s via CLSIG (%s)\n", __func__, + pindex->GetBlockHash().ToString(), clsig->ToString()); + m_chainstate.EnforceBlock(dummy_state, pindex); + + + if (/*activateNeeded =*/WITH_LOCK(::cs_main, return m_chainstate.m_chain.Tip()->GetAncestor( + currentBestChainLockBlockIndex->nHeight)) != + currentBestChainLockBlockIndex) { + if (!m_chainstate.ActivateBestChain(dummy_state)) { + LogPrintf("CChainLocksHandler::%s -- ActivateBestChain failed: %s\n", __func__, dummy_state.ToString()); + return; + } + LOCK(::cs_main); + if (m_chainstate.m_chain.Tip()->GetAncestor(currentBestChainLockBlockIndex->nHeight) != + currentBestChainLockBlockIndex) { + return; + } + } + + { + LOCK(cs); + if (lastNotifyChainLockBlockIndex == currentBestChainLockBlockIndex) return; + lastNotifyChainLockBlockIndex = currentBestChainLockBlockIndex; + } + + GetMainSignals().NotifyChainLock(currentBestChainLockBlockIndex, clsig, clsig->ToString()); + uiInterface.NotifyChainLock(clsig->getBlockHash().ToString(), clsig->getHeight()); + ::g_stats_client->gauge("chainlocks.blockHeight", clsig->getHeight(), 1.0f); +} + +VerifyRecSigStatus CChainLocksHandler::VerifyChainLock(const chainlock::ChainLockSig& clsig) const +{ + const auto llmqType = Params().GetConsensus().llmqTypeChainLocks; + const uint256 nRequestId = chainlock::GenSigRequestId(clsig.getHeight()); + + return llmq::VerifyRecoveredSig(llmqType, m_chainstate.m_chain, qman, clsig.getHeight(), nRequestId, + clsig.getBlockHash(), clsig.getSig()); +} + +bool CChainLocksHandler::HasChainLock(int nHeight, const uint256& blockHash) const +{ + AssertLockNotHeld(cs); + LOCK(cs); + + if (!IsEnabled()) { + return false; + } + + if (bestChainLockBlockIndex == nullptr) { + return false; + } + + if (nHeight > bestChainLockBlockIndex->nHeight) { + return false; + } + + if (nHeight == bestChainLockBlockIndex->nHeight) { + return blockHash == bestChainLockBlockIndex->GetBlockHash(); + } + + const auto* pAncestor = bestChainLockBlockIndex->GetAncestor(nHeight); + return (pAncestor != nullptr) && pAncestor->GetBlockHash() == blockHash; +} + +bool CChainLocksHandler::HasConflictingChainLock(int nHeight, const uint256& blockHash) const +{ + AssertLockNotHeld(cs); + LOCK(cs); + + if (!IsEnabled()) { + return false; + } + + if (bestChainLockBlockIndex == nullptr) { + return false; + } + + if (nHeight > bestChainLockBlockIndex->nHeight) { + return false; + } + + if (nHeight == bestChainLockBlockIndex->nHeight) { + return blockHash != bestChainLockBlockIndex->GetBlockHash(); + } + + const auto* pAncestor = bestChainLockBlockIndex->GetAncestor(nHeight); + assert(pAncestor); + return pAncestor->GetBlockHash() != blockHash; +} + +void CChainLocksHandler::Cleanup() +{ + if (!m_mn_sync.IsBlockchainSynced()) { + return; + } + + if (GetTime() - lastCleanupTime.load() < CLEANUP_INTERVAL) { + return; + } + lastCleanupTime = GetTime(); + + { + LOCK(cs); + for (auto it = seenChainLocks.begin(); it != seenChainLocks.end();) { + if (GetTime() - it->second >= CLEANUP_SEEN_TIMEOUT) { + it = seenChainLocks.erase(it); + } else { + ++it; + } + } + } + + if (m_signer) { + const auto cleanup_txes{m_signer->Cleanup()}; + LOCK(cs); + for (const auto& tx : cleanup_txes) { + for (const auto& txid : *tx) { + txFirstSeenTime.erase(txid); + } + } + } + + LOCK(::cs_main); + LOCK2(mempool.cs, cs); // need mempool.cs due to GetTransaction calls + for (auto it = txFirstSeenTime.begin(); it != txFirstSeenTime.end();) { + uint256 hashBlock; + if (auto tx = GetTransaction(nullptr, &mempool, it->first, Params().GetConsensus(), hashBlock); !tx) { + // tx has vanished, probably due to conflicts + it = txFirstSeenTime.erase(it); + } else if (!hashBlock.IsNull()) { + const auto* pindex = m_chainstate.m_blockman.LookupBlockIndex(hashBlock); + assert(pindex); // GetTransaction gave us that hashBlock, it should resolve to a valid block index + if (m_chainstate.m_chain.Tip()->GetAncestor(pindex->nHeight) == pindex && + m_chainstate.m_chain.Height() - pindex->nHeight > chainlock::TX_CONFIRM_THRESHOLD) { + // tx is sufficiently deep, we can stop tracking it + it = txFirstSeenTime.erase(it); + } else { + ++it; + } + } else { + ++it; + } + } +} +} // namespace llmq diff --git a/src/chainlock/chainlock.h b/src/chainlock/chainlock.h new file mode 100644 index 000000000000..e7060537df4c --- /dev/null +++ b/src/chainlock/chainlock.h @@ -0,0 +1,125 @@ +// Copyright (c) 2019-2025 The Dash Core developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_CHAINLOCK_CHAINLOCK_H +#define BITCOIN_CHAINLOCK_CHAINLOCK_H + +#include + +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include + +class CBlock; +class CBlockIndex; +class CChainState; +class CMasternodeSync; +class CScheduler; +class CSporkManager; +class CTxMemPool; + +namespace llmq { +class CInstantSendManager; +class CQuorumManager; +class CSigningManager; +class CSigSharesManager; +enum class VerifyRecSigStatus; + +class CChainLocksHandler final : public chainlock::ChainLockSignerParent +{ +private: + CChainState& m_chainstate; + CQuorumManager& qman; + CSporkManager& spork_manager; + CTxMemPool& mempool; + const CMasternodeSync& m_mn_sync; + std::unique_ptr scheduler; + std::unique_ptr scheduler_thread; + + std::unique_ptr m_signer{nullptr}; + + mutable Mutex cs; + std::atomic tryLockChainTipScheduled{false}; + std::atomic isEnabled{false}; + + uint256 bestChainLockHash GUARDED_BY(cs); + chainlock::ChainLockSig bestChainLock GUARDED_BY(cs); + + chainlock::ChainLockSig bestChainLockWithKnownBlock GUARDED_BY(cs); + const CBlockIndex* bestChainLockBlockIndex GUARDED_BY(cs){nullptr}; + const CBlockIndex* lastNotifyChainLockBlockIndex GUARDED_BY(cs){nullptr}; + + std::unordered_map txFirstSeenTime GUARDED_BY(cs); + + std::map seenChainLocks GUARDED_BY(cs); + + std::atomic lastCleanupTime{0s}; + +public: + explicit CChainLocksHandler(CChainState& chainstate, CQuorumManager& _qman, CSigningManager& _sigman, + CSigSharesManager& _shareman, CSporkManager& sporkman, CTxMemPool& _mempool, + const CMasternodeSync& mn_sync, bool is_masternode); + ~CChainLocksHandler(); + + void Start(const llmq::CInstantSendManager& isman); + void Stop(); + + bool AlreadyHave(const CInv& inv) const + EXCLUSIVE_LOCKS_REQUIRED(!cs); + bool GetChainLockByHash(const uint256& hash, chainlock::ChainLockSig& ret) const + EXCLUSIVE_LOCKS_REQUIRED(!cs); + chainlock::ChainLockSig GetBestChainLock() const + EXCLUSIVE_LOCKS_REQUIRED(!cs); + void UpdateTxFirstSeenMap(const std::unordered_set& tx, const int64_t& time) override + EXCLUSIVE_LOCKS_REQUIRED(!cs); + + [[nodiscard]] MessageProcessingResult ProcessNewChainLock(NodeId from, const chainlock::ChainLockSig& clsig, + const uint256& hash) override + EXCLUSIVE_LOCKS_REQUIRED(!cs); + + void AcceptedBlockHeader(gsl::not_null pindexNew) + EXCLUSIVE_LOCKS_REQUIRED(!cs); + void UpdatedBlockTip(const llmq::CInstantSendManager& isman); + void TransactionAddedToMempool(const CTransactionRef& tx, int64_t nAcceptTime) + EXCLUSIVE_LOCKS_REQUIRED(!cs); + void BlockConnected(const std::shared_ptr& pblock, gsl::not_null pindex) + EXCLUSIVE_LOCKS_REQUIRED(!cs); + void BlockDisconnected(const std::shared_ptr& pblock, gsl::not_null pindexDisconnected) + EXCLUSIVE_LOCKS_REQUIRED(!cs); + void CheckActiveState() + EXCLUSIVE_LOCKS_REQUIRED(!cs); + void EnforceBestChainLock() + EXCLUSIVE_LOCKS_REQUIRED(!cs); + + bool HasChainLock(int nHeight, const uint256& blockHash) const override + EXCLUSIVE_LOCKS_REQUIRED(!cs); + bool HasConflictingChainLock(int nHeight, const uint256& blockHash) const override + EXCLUSIVE_LOCKS_REQUIRED(!cs); + VerifyRecSigStatus VerifyChainLock(const chainlock::ChainLockSig& clsig) const; + + [[nodiscard]] int32_t GetBestChainLockHeight() const override + EXCLUSIVE_LOCKS_REQUIRED(!cs); + bool IsTxSafeForMining(const uint256& txid) const override + EXCLUSIVE_LOCKS_REQUIRED(!cs); + [[nodiscard]] bool IsEnabled() const override { return isEnabled; } + +private: + void Cleanup() + EXCLUSIVE_LOCKS_REQUIRED(!cs); +}; + +bool AreChainLocksEnabled(const CSporkManager& sporkman); +} // namespace llmq + +#endif // BITCOIN_CHAINLOCK_CHAINLOCK_H diff --git a/src/chainlock/clsig.cpp b/src/chainlock/clsig.cpp new file mode 100644 index 000000000000..e781a2eb10ac --- /dev/null +++ b/src/chainlock/clsig.cpp @@ -0,0 +1,33 @@ +// Copyright (c) 2021-2022 The Dash Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include + +#include + +namespace chainlock { +static constexpr std::string_view CLSIG_REQUESTID_PREFIX{"clsig"}; + +ChainLockSig::ChainLockSig() = default; +ChainLockSig::~ChainLockSig() = default; + +ChainLockSig::ChainLockSig(int32_t nHeight, const uint256& blockHash, const CBLSSignature& sig) : + nHeight{nHeight}, + blockHash{blockHash}, + sig{sig} +{ +} + +std::string ChainLockSig::ToString() const +{ + return strprintf("ChainLockSig(nHeight=%d, blockHash=%s)", nHeight, blockHash.ToString()); +} + +uint256 GenSigRequestId(const int32_t nHeight) +{ + return ::SerializeHash(std::make_pair(CLSIG_REQUESTID_PREFIX, nHeight)); +} +} // namespace chainlock diff --git a/src/chainlock/clsig.h b/src/chainlock/clsig.h new file mode 100644 index 000000000000..6cd532ce6248 --- /dev/null +++ b/src/chainlock/clsig.h @@ -0,0 +1,44 @@ +// Copyright (c) 2019-2022 The Dash Core developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_CHAINLOCK_CLSIG_H +#define BITCOIN_CHAINLOCK_CLSIG_H + +#include +#include + +#include + +#include + +namespace chainlock { +struct ChainLockSig { +private: + int32_t nHeight{-1}; + uint256 blockHash; + CBLSSignature sig; + +public: + ChainLockSig(); + ~ChainLockSig(); + + ChainLockSig(int32_t nHeight, const uint256& blockHash, const CBLSSignature& sig); + + [[nodiscard]] int32_t getHeight() const { return nHeight; } + [[nodiscard]] const uint256& getBlockHash() const { return blockHash; } + [[nodiscard]] const CBLSSignature& getSig() const { return sig; } + [[nodiscard]] bool IsNull() const { return nHeight == -1 && blockHash == uint256(); } + [[nodiscard]] std::string ToString() const; + + SERIALIZE_METHODS(ChainLockSig, obj) + { + READWRITE(obj.nHeight, obj.blockHash, obj.sig); + } +}; + +//! Generate clsig request ID with block height +uint256 GenSigRequestId(const int32_t nHeight); +} // namespace chainlock + +#endif // BITCOIN_CHAINLOCK_CLSIG_H diff --git a/src/chainlock/signing.cpp b/src/chainlock/signing.cpp new file mode 100644 index 000000000000..ef5a3513f990 --- /dev/null +++ b/src/chainlock/signing.cpp @@ -0,0 +1,266 @@ +// Copyright (c) 2019-2025 The Dash Core 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 + +using node::ReadBlockFromDisk; + +namespace chainlock { +ChainLockSigner::ChainLockSigner(CChainState& chainstate, ChainLockSignerParent& clhandler, + llmq::CSigningManager& sigman, llmq::CSigSharesManager& shareman, + CSporkManager& sporkman, const CMasternodeSync& mn_sync) : + m_chainstate{chainstate}, + m_clhandler{clhandler}, + m_sigman{sigman}, + m_shareman{shareman}, + m_sporkman{sporkman}, + m_mn_sync{mn_sync} +{ +} + +ChainLockSigner::~ChainLockSigner() = default; + +void ChainLockSigner::Start() +{ + m_sigman.RegisterRecoveredSigsListener(this); +} + +void ChainLockSigner::Stop() +{ + m_sigman.UnregisterRecoveredSigsListener(this); +} + +void ChainLockSigner::TrySignChainTip(const llmq::CInstantSendManager& isman) +{ + if (!m_mn_sync.IsBlockchainSynced()) { + return; + } + + if (!m_clhandler.IsEnabled()) { + return; + } + + if (m_sporkman.GetSporkValue(SPORK_19_CHAINLOCKS_ENABLED) != 0) { + // ChainLocks signing not enabled + return; + } + + const CBlockIndex* pindex = WITH_LOCK(::cs_main, return m_chainstate.m_chain.Tip()); + + if (!pindex || !pindex->pprev) { + return; + } + + // DIP8 defines a process called "Signing attempts" which should run before the CLSIG is finalized + // To simplify the initial implementation, we skip this process and directly try to create a CLSIG + // This will fail when multiple blocks compete, but we accept this for the initial implementation. + // Later, we'll add the multiple attempts process. + + { + LOCK(cs_signer); + + if (pindex->nHeight == lastSignedHeight) { + // already signed this one + return; + } + } + + if (m_clhandler.GetBestChainLockHeight() >= pindex->nHeight) { + // already got the same CLSIG or a better one + return; + } + + if (m_clhandler.HasConflictingChainLock(pindex->nHeight, pindex->GetBlockHash())) { + // don't sign if another conflicting CLSIG is already present. EnforceBestChainLock will later enforce + // the correct chain. + return; + } + + LogPrint(BCLog::CHAINLOCKS, "%s -- trying to sign %s, height=%d\n", __func__, pindex->GetBlockHash().ToString(), + pindex->nHeight); + + // When the new IX system is activated, we only try to ChainLock blocks which include safe transactions. A TX is + // considered safe when it is islocked or at least known since 10 minutes (from mempool or block). These checks are + // performed for the tip (which we try to sign) and the previous 5 blocks. If a ChainLocked block is found on the + // way down, we consider all TXs to be safe. + if (isman.IsInstantSendEnabled() && isman.RejectConflictingBlocks()) { + const auto* pindexWalk = pindex; + while (pindexWalk != nullptr) { + if (pindex->nHeight - pindexWalk->nHeight > TX_CONFIRM_THRESHOLD) { + // no need to check further down, safe to assume that TXs below this height won't be + // islocked anymore if they aren't already + LogPrint(BCLog::CHAINLOCKS, "%s -- tip and previous %d blocks all safe\n", __func__, TX_CONFIRM_THRESHOLD); + break; + } + if (m_clhandler.HasChainLock(pindexWalk->nHeight, pindexWalk->GetBlockHash())) { + // we don't care about islocks for TXs that are ChainLocked already + LogPrint(BCLog::CHAINLOCKS, "%s -- chainlock at height %d\n", __func__, pindexWalk->nHeight); + break; + } + + auto txids = GetBlockTxs(pindexWalk->GetBlockHash()); + if (!txids) { + pindexWalk = pindexWalk->pprev; + continue; + } + + for (const auto& txid : *txids) { + if (!m_clhandler.IsTxSafeForMining(txid) && !isman.IsLocked(txid)) { + LogPrint(BCLog::CHAINLOCKS, /* Continued */ + "%s -- not signing block %s due to TX %s not being islocked and not old enough.\n", + __func__, pindexWalk->GetBlockHash().ToString(), txid.ToString()); + return; + } + } + + pindexWalk = pindexWalk->pprev; + } + } + + uint256 requestId = GenSigRequestId(pindex->nHeight); + uint256 msgHash = pindex->GetBlockHash(); + + if (m_clhandler.GetBestChainLockHeight() >= pindex->nHeight) { + // might have happened while we didn't hold cs + return; + } + { + LOCK(cs_signer); + lastSignedHeight = pindex->nHeight; + lastSignedRequestId = requestId; + lastSignedMsgHash = msgHash; + } + + m_sigman.AsyncSignIfMember(Params().GetConsensus().llmqTypeChainLocks, m_shareman, requestId, msgHash); +} + +void ChainLockSigner::EraseFromBlockHashTxidMap(const uint256& hash) +{ + AssertLockNotHeld(cs_signer); + LOCK(cs_signer); + blockTxs.erase(hash); +} + +void ChainLockSigner::UpdateBlockHashTxidMap(const uint256& hash, const std::vector& vtx) +{ + AssertLockNotHeld(cs_signer); + LOCK(cs_signer); + auto it = blockTxs.find(hash); + if (it == blockTxs.end()) { + // We must create this entry even if there are no lockable transactions in the block, so that TrySignChainTip + // later knows about this block + it = blockTxs.emplace(hash, std::make_shared>()).first; + } + auto& txids = *it->second; + for (const auto& tx : vtx) { + if (!tx->IsCoinBase() && !tx->vin.empty()) { + txids.emplace(tx->GetHash()); + } + } +} + +ChainLockSigner::BlockTxs::mapped_type ChainLockSigner::GetBlockTxs(const uint256& blockHash) +{ + AssertLockNotHeld(cs_signer); + AssertLockNotHeld(::cs_main); + + ChainLockSigner::BlockTxs::mapped_type ret; + + { + LOCK(cs_signer); + auto it = blockTxs.find(blockHash); + if (it != blockTxs.end()) { + ret = it->second; + } + } + if (!ret) { + // This should only happen when freshly started. + // If running for some time, SyncTransaction should have been called before which fills blockTxs. + LogPrint(BCLog::CHAINLOCKS, "%s -- blockTxs for %s not found. Trying ReadBlockFromDisk\n", __func__, + blockHash.ToString()); + + uint32_t blockTime; + { + LOCK(::cs_main); + const auto* pindex = m_chainstate.m_blockman.LookupBlockIndex(blockHash); + if (!pindex) { + return nullptr; + } + CBlock block; + if (!ReadBlockFromDisk(block, pindex, Params().GetConsensus())) { + return nullptr; + } + + ret = std::make_shared>(); + for (const auto& tx : block.vtx) { + if (tx->IsCoinBase() || tx->vin.empty()) { + continue; + } + ret->emplace(tx->GetHash()); + } + + blockTime = block.nTime; + } + { + LOCK(cs_signer); + blockTxs.emplace(blockHash, ret); + } + m_clhandler.UpdateTxFirstSeenMap(*ret, blockTime); + } + return ret; +} + +MessageProcessingResult ChainLockSigner::HandleNewRecoveredSig(const llmq::CRecoveredSig& recoveredSig) +{ + if (!m_clhandler.IsEnabled()) { + return {}; + } + + ChainLockSig clsig; + { + LOCK(cs_signer); + + if (recoveredSig.getId() != lastSignedRequestId || recoveredSig.getMsgHash() != lastSignedMsgHash) { + // this is not what we signed, so lets not create a CLSIG for it + return {}; + } + if (m_clhandler.GetBestChainLockHeight() >= lastSignedHeight) { + // already got the same or a better CLSIG through the CLSIG message + return {}; + } + + clsig = ChainLockSig(lastSignedHeight, lastSignedMsgHash, recoveredSig.sig.Get()); + } + return m_clhandler.ProcessNewChainLock(-1, clsig, ::SerializeHash(clsig)); +} + +std::vector>> ChainLockSigner::Cleanup() +{ + AssertLockNotHeld(cs_signer); + std::vector>> removed; + LOCK2(::cs_main, cs_signer); + for (auto it = blockTxs.begin(); it != blockTxs.end();) { + const auto* pindex = m_chainstate.m_blockman.LookupBlockIndex(it->first); + if (!pindex) { + it = blockTxs.erase(it); + } else if (m_clhandler.HasChainLock(pindex->nHeight, pindex->GetBlockHash())) { + removed.push_back(it->second); + it = blockTxs.erase(it); + } else if (m_clhandler.HasConflictingChainLock(pindex->nHeight, pindex->GetBlockHash())) { + it = blockTxs.erase(it); + } else { + ++it; + } + } + return removed; +} +} // namespace chainlock diff --git a/src/chainlock/signing.h b/src/chainlock/signing.h new file mode 100644 index 000000000000..18a7727cf8e1 --- /dev/null +++ b/src/chainlock/signing.h @@ -0,0 +1,92 @@ +// Copyright (c) 2019-2025 The Dash Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_CHAINLOCK_SIGNING_H +#define BITCOIN_CHAINLOCK_SIGNING_H + +#include +#include + +class CMasternodeSync; +class CSporkManager; +struct MessageProcessingResult; +namespace llmq { +class CChainLocksHandler; +class CInstantSendManager; +class CRecoveredSig; +class CSigningManager; +class CSigSharesManager; +} // namespace llmq + +namespace chainlock { +//! Depth of block including transactions before it's considered safe +static constexpr int32_t TX_CONFIRM_THRESHOLD{5}; + +class ChainLockSignerParent +{ +public: + virtual ~ChainLockSignerParent() = default; + + virtual int32_t GetBestChainLockHeight() const = 0; + virtual bool HasChainLock(int nHeight, const uint256& blockHash) const = 0; + virtual bool HasConflictingChainLock(int nHeight, const uint256& blockHash) const = 0; + virtual bool IsEnabled() const = 0; + virtual bool IsTxSafeForMining(const uint256& txid) const = 0; + [[nodiscard]] virtual MessageProcessingResult ProcessNewChainLock(NodeId from, const ChainLockSig& clsig, const uint256& hash) = 0; + virtual void UpdateTxFirstSeenMap(const std::unordered_set& tx, const int64_t& time) = 0; +}; + +class ChainLockSigner final : public llmq::CRecoveredSigsListener +{ +private: + CChainState& m_chainstate; + ChainLockSignerParent& m_clhandler; + llmq::CSigningManager& m_sigman; + llmq::CSigSharesManager& m_shareman; + CSporkManager& m_sporkman; + const CMasternodeSync& m_mn_sync; + +private: + // We keep track of txids from recently received blocks so that we can check if all TXs got islocked + struct BlockHasher { + size_t operator()(const uint256& hash) const { return ReadLE64(hash.begin()); } + }; + using BlockTxs = std::unordered_map>, BlockHasher>; + +private: + mutable Mutex cs_signer; + + BlockTxs blockTxs GUARDED_BY(cs_signer); + int32_t lastSignedHeight GUARDED_BY(cs_signer){-1}; + uint256 lastSignedRequestId GUARDED_BY(cs_signer); + uint256 lastSignedMsgHash GUARDED_BY(cs_signer); + +public: + explicit ChainLockSigner(CChainState& chainstate, ChainLockSignerParent& clhandler, llmq::CSigningManager& sigman, + llmq::CSigSharesManager& shareman, CSporkManager& sporkman, const CMasternodeSync& mn_sync); + ~ChainLockSigner(); + + void Start(); + void Stop(); + + void EraseFromBlockHashTxidMap(const uint256& hash) + EXCLUSIVE_LOCKS_REQUIRED(!cs_signer); + void UpdateBlockHashTxidMap(const uint256& hash, const std::vector& vtx) + EXCLUSIVE_LOCKS_REQUIRED(!cs_signer); + + void TrySignChainTip(const llmq::CInstantSendManager& isman) + EXCLUSIVE_LOCKS_REQUIRED(!cs_signer); + [[nodiscard]] MessageProcessingResult HandleNewRecoveredSig(const llmq::CRecoveredSig& recoveredSig) override + EXCLUSIVE_LOCKS_REQUIRED(!cs_signer); + + [[nodiscard]] std::vector>> Cleanup() + EXCLUSIVE_LOCKS_REQUIRED(!cs_signer); + +private: + [[nodiscard]] BlockTxs::mapped_type GetBlockTxs(const uint256& blockHash) + EXCLUSIVE_LOCKS_REQUIRED(!cs_signer); +}; +} // namespace chainlock + +#endif // BITCOIN_CHAINLOCK_SIGNING_H diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 086870394029..31d47f4d4d12 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -820,9 +820,9 @@ class CRegTestParams : public CChainParams { consensus.vDeployments[Consensus::DEPLOYMENT_V23].bit = 12; consensus.vDeployments[Consensus::DEPLOYMENT_V23].nStartTime = 0; consensus.vDeployments[Consensus::DEPLOYMENT_V23].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; - consensus.vDeployments[Consensus::DEPLOYMENT_V23].nWindowSize = 350; - consensus.vDeployments[Consensus::DEPLOYMENT_V23].nThresholdStart = 350 / 5 * 4; // 80% of window size - consensus.vDeployments[Consensus::DEPLOYMENT_V23].nThresholdMin = 350 / 5 * 3; // 60% of window size + consensus.vDeployments[Consensus::DEPLOYMENT_V23].nWindowSize = 250; + consensus.vDeployments[Consensus::DEPLOYMENT_V23].nThresholdStart = 250 / 5 * 4; // 80% of window size + consensus.vDeployments[Consensus::DEPLOYMENT_V23].nThresholdMin = 250 / 5 * 3; // 60% of window size consensus.vDeployments[Consensus::DEPLOYMENT_V23].nFalloffCoeff = 5; // this corresponds to 10 periods consensus.vDeployments[Consensus::DEPLOYMENT_V23].useEHF = true; diff --git a/src/coinjoin/client.cpp b/src/coinjoin/client.cpp index 35593152c8b2..543bce8f0a32 100644 --- a/src/coinjoin/client.cpp +++ b/src/coinjoin/client.cpp @@ -38,33 +38,27 @@ using wallet::CoinType; using wallet::CWallet; using wallet::ReserveDestination; -PeerMsgRet CCoinJoinClientQueueManager::ProcessMessage(const CNode& peer, CConnman& connman, PeerManager& peerman, - std::string_view msg_type, CDataStream& vRecv) +MessageProcessingResult CCoinJoinClientQueueManager::ProcessMessage(NodeId from, CConnman& connman, PeerManager& peerman, + std::string_view msg_type, CDataStream& vRecv) { + if (msg_type != NetMsgType::DSQUEUE) { + return {}; + } + if (m_is_masternode) return {}; if (!m_mn_sync.IsBlockchainSynced()) return {}; - if (msg_type == NetMsgType::DSQUEUE) { - return CCoinJoinClientQueueManager::ProcessDSQueue(peer, connman, peerman, vRecv); - } - return {}; -} - -PeerMsgRet CCoinJoinClientQueueManager::ProcessDSQueue(const CNode& peer, CConnman& connman, PeerManager& peerman, - CDataStream& vRecv) -{ assert(m_mn_metaman.IsValid()); CCoinJoinQueue dsq; vRecv >> dsq; - { - LOCK(::cs_main); - peerman.EraseObjectRequest(peer.GetId(), CInv(MSG_DSQ, dsq.GetHash())); - } + MessageProcessingResult ret{}; + ret.m_to_erase = CInv{MSG_DSQ, dsq.GetHash()}; if (dsq.masternodeOutpoint.IsNull() && dsq.m_protxHash.IsNull()) { - return tl::unexpected{100}; + ret.m_error = MisbehavingError{100}; + return ret; } const auto tip_mn_list = m_dmnman.GetListAtChainTip(); @@ -72,7 +66,8 @@ PeerMsgRet CCoinJoinClientQueueManager::ProcessDSQueue(const CNode& peer, CConnm if (auto dmn = tip_mn_list.GetValidMN(dsq.m_protxHash)) { dsq.masternodeOutpoint = dmn->collateralOutpoint; } else { - return tl::unexpected{10}; + ret.m_error = MisbehavingError{10}; + return ret; } } @@ -84,31 +79,32 @@ PeerMsgRet CCoinJoinClientQueueManager::ProcessDSQueue(const CNode& peer, CConnm // process every dsq only once for (const auto &q: vecCoinJoinQueue) { if (q == dsq) { - return {}; + return ret; } if (q.fReady == dsq.fReady && q.masternodeOutpoint == dsq.masternodeOutpoint) { // no way the same mn can send another dsq with the same readiness this soon LogPrint(BCLog::COINJOIN, /* Continued */ - "DSQUEUE -- Peer %s is sending WAY too many dsq messages for a masternode with collateral %s\n", - peer.GetLogString(), dsq.masternodeOutpoint.ToStringShort()); - return {}; + "DSQUEUE -- Peer %d is sending WAY too many dsq messages for a masternode with collateral %s\n", + from, dsq.masternodeOutpoint.ToStringShort()); + return ret; } } } // cs_vecqueue LogPrint(BCLog::COINJOIN, "DSQUEUE -- %s new\n", dsq.ToString()); - if (dsq.IsTimeOutOfBounds()) return {}; + if (dsq.IsTimeOutOfBounds()) return ret; auto dmn = tip_mn_list.GetValidMNByCollateral(dsq.masternodeOutpoint); - if (!dmn) return {}; + if (!dmn) return ret; if (dsq.m_protxHash.IsNull()) { dsq.m_protxHash = dmn->proTxHash; } if (!dsq.CheckSignature(dmn->pdmnState->pubKeyOperator.Get())) { - return tl::unexpected{10}; + ret.m_error = MisbehavingError{10}; + return ret; } // if the queue is ready, submit if we can @@ -117,7 +113,7 @@ PeerMsgRet CCoinJoinClientQueueManager::ProcessDSQueue(const CNode& peer, CConnm return clientman->TrySubmitDenominate(dmn->proTxHash, connman); })) { LogPrint(BCLog::COINJOIN, "DSQUEUE -- CoinJoin queue is ready, masternode=%s, queue=%s\n", dmn->proTxHash.ToString(), dsq.ToString()); - return {}; + return ret; } else { int64_t nLastDsq = m_mn_metaman.GetMetaInfo(dmn->proTxHash)->GetLastDsq(); int64_t nDsqThreshold = m_mn_metaman.GetDsqThreshold(dmn->proTxHash, tip_mn_list.GetValidMNsCount()); @@ -127,7 +123,7 @@ PeerMsgRet CCoinJoinClientQueueManager::ProcessDSQueue(const CNode& peer, CConnm if (nLastDsq != 0 && nDsqThreshold > m_mn_metaman.GetDsqCount()) { LogPrint(BCLog::COINJOIN, "DSQUEUE -- Masternode %s is sending too many dsq messages\n", dmn->proTxHash.ToString()); - return {}; + return ret; } m_mn_metaman.AllowMixing(dmn->proTxHash); @@ -142,7 +138,7 @@ PeerMsgRet CCoinJoinClientQueueManager::ProcessDSQueue(const CNode& peer, CConnm } } // cs_ProcessDSQueue peerman.RelayDSQ(dsq); - return {}; + return ret; } void CCoinJoinClientManager::ProcessMessage(CNode& peer, CChainState& active_chainstate, CConnman& connman, const CTxMemPool& mempool, std::string_view msg_type, CDataStream& vRecv) @@ -1556,7 +1552,7 @@ bool CCoinJoinClientSession::CreateCollateralTransaction(CMutableTransaction& tx AssertLockHeld(m_wallet->cs_wallet); CCoinControl coin_control(CoinType::ONLY_COINJOIN_COLLATERAL); - std::vector vCoins{AvailableCoinsListUnspent(*m_wallet, &coin_control).coins}; + std::vector vCoins{AvailableCoinsListUnspent(*m_wallet, &coin_control).all()}; if (vCoins.empty()) { strReason = strprintf("%s requires a collateral transaction and could not locate an acceptable input!", gCoinJoinName); return false; @@ -1575,11 +1571,10 @@ bool CCoinJoinClientSession::CreateCollateralTransaction(CMutableTransaction& tx if (txout.nValue >= CoinJoin::GetCollateralAmount() * 2) { // make our change address CScript scriptChange; - CTxDestination dest; ReserveDestination reserveDest(m_wallet.get()); - bool success = reserveDest.GetReservedDestination(dest, true); - assert(success); // should never fail, as we just unlocked - scriptChange = GetScriptForDestination(dest); + auto dest_opt = reserveDest.GetReservedDestination(true); + assert(dest_opt); // should never fail, as we just unlocked + scriptChange = GetScriptForDestination(*dest_opt); reserveDest.KeepDestination(); // return change txCollateral.vout.emplace_back(txout.nValue - CoinJoin::GetCollateralAmount(), scriptChange); diff --git a/src/coinjoin/client.h b/src/coinjoin/client.h index bdeaccc7d9db..7d403e33bd36 100644 --- a/src/coinjoin/client.h +++ b/src/coinjoin/client.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -252,9 +253,9 @@ class CCoinJoinClientQueueManager : public CCoinJoinBaseManager m_mn_sync(mn_sync), m_is_masternode{is_masternode} {}; - PeerMsgRet ProcessMessage(const CNode& peer, CConnman& connman, PeerManager& peerman, std::string_view msg_type, - CDataStream& vRecv) EXCLUSIVE_LOCKS_REQUIRED(!cs_vecqueue); - PeerMsgRet ProcessDSQueue(const CNode& peer, CConnman& connman, PeerManager& peerman, CDataStream& vRecv); + [[nodiscard]] MessageProcessingResult ProcessMessage(NodeId from, CConnman& connman, PeerManager& peerman, std::string_view msg_type, + CDataStream& vRecv) + EXCLUSIVE_LOCKS_REQUIRED(!cs_vecqueue); void DoMaintenance(); }; diff --git a/src/coinjoin/coinjoin.cpp b/src/coinjoin/coinjoin.cpp index 641a1e7c02d3..07ddb2018090 100644 --- a/src/coinjoin/coinjoin.cpp +++ b/src/coinjoin/coinjoin.cpp @@ -4,20 +4,21 @@ #include -#include #include #include -#include -#include -#include -#include #include #include #include #include #include - #include + +#include +#include +#include +#include +#include + #include constexpr static CAmount DEFAULT_MAX_RAW_TX_FEE{COIN / 10}; diff --git a/src/coinjoin/coinjoin.h b/src/coinjoin/coinjoin.h index 5eac1470be35..d69d6c12d051 100644 --- a/src/coinjoin/coinjoin.h +++ b/src/coinjoin/coinjoin.h @@ -287,6 +287,8 @@ class CCoinJoinBroadcastTx bool Sign(const CActiveMasternodeManager& mn_activeman); [[nodiscard]] bool CheckSignature(const CBLSPublicKey& blsPubKey) const; + // Used only for unit tests + [[nodiscard]] std::optional GetConfirmedHeight() const { return nConfirmedHeight; } void SetConfirmedHeight(std::optional nConfirmedHeightIn) { assert(nConfirmedHeightIn == std::nullopt || *nConfirmedHeightIn > 0); nConfirmedHeight = nConfirmedHeightIn; } bool IsExpired(const CBlockIndex* pindex, const llmq::CChainLocksHandler& clhandler) const; [[nodiscard]] bool IsValidStructure() const; diff --git a/src/coinjoin/server.cpp b/src/coinjoin/server.cpp index a90df185ef1a..ad068dc59db1 100644 --- a/src/coinjoin/server.cpp +++ b/src/coinjoin/server.cpp @@ -23,7 +23,7 @@ #include -PeerMsgRet CCoinJoinServer::ProcessMessage(CNode& peer, std::string_view msg_type, CDataStream& vRecv) +MessageProcessingResult CCoinJoinServer::ProcessMessage(CNode& peer, std::string_view msg_type, CDataStream& vRecv) { if (!m_mn_activeman) return {}; if (!m_mn_sync.IsBlockchainSynced()) return {}; @@ -31,7 +31,7 @@ PeerMsgRet CCoinJoinServer::ProcessMessage(CNode& peer, std::string_view msg_typ if (msg_type == NetMsgType::DSACCEPT) { ProcessDSACCEPT(peer, vRecv); } else if (msg_type == NetMsgType::DSQUEUE) { - return ProcessDSQUEUE(peer, vRecv); + return ProcessDSQUEUE(peer.GetId(), vRecv); } else if (msg_type == NetMsgType::DSVIN) { ProcessDSVIN(peer, vRecv); } else if (msg_type == NetMsgType::DSSIGNFINALTX) { @@ -109,20 +109,19 @@ void CCoinJoinServer::ProcessDSACCEPT(CNode& peer, CDataStream& vRecv) } } -PeerMsgRet CCoinJoinServer::ProcessDSQUEUE(const CNode& peer, CDataStream& vRecv) +MessageProcessingResult CCoinJoinServer::ProcessDSQUEUE(NodeId from, CDataStream& vRecv) { assert(m_mn_metaman.IsValid()); CCoinJoinQueue dsq; vRecv >> dsq; - { - LOCK(::cs_main); - Assert(m_peerman)->EraseObjectRequest(peer.GetId(), CInv(MSG_DSQ, dsq.GetHash())); - } + MessageProcessingResult ret{}; + ret.m_to_erase = CInv{MSG_DSQ, dsq.GetHash()}; if (dsq.masternodeOutpoint.IsNull() && dsq.m_protxHash.IsNull()) { - return tl::unexpected{100}; + ret.m_error = MisbehavingError{100}; + return ret; } const auto tip_mn_list = m_dmnman.GetListAtChainTip(); @@ -130,40 +129,42 @@ PeerMsgRet CCoinJoinServer::ProcessDSQUEUE(const CNode& peer, CDataStream& vRecv if (auto dmn = tip_mn_list.GetValidMN(dsq.m_protxHash)) { dsq.masternodeOutpoint = dmn->collateralOutpoint; } else { - return tl::unexpected{10}; + ret.m_error = MisbehavingError{10}; + return ret; } } { TRY_LOCK(cs_vecqueue, lockRecv); - if (!lockRecv) return {}; + if (!lockRecv) return ret; // process every dsq only once for (const auto& q : vecCoinJoinQueue) { if (q == dsq) { - return {}; + return ret; } if (q.fReady == dsq.fReady && q.masternodeOutpoint == dsq.masternodeOutpoint) { // no way the same mn can send another dsq with the same readiness this soon - LogPrint(BCLog::COINJOIN, "DSQUEUE -- Peer %s is sending WAY too many dsq messages for a masternode with collateral %s\n", peer.GetLogString(), dsq.masternodeOutpoint.ToStringShort()); - return {}; + LogPrint(BCLog::COINJOIN, "DSQUEUE -- Peer %d is sending WAY too many dsq messages for a masternode with collateral %s\n", from, dsq.masternodeOutpoint.ToStringShort()); + return ret; } } } // cs_vecqueue LogPrint(BCLog::COINJOIN, "DSQUEUE -- %s new\n", dsq.ToString()); - if (dsq.IsTimeOutOfBounds()) return {}; + if (dsq.IsTimeOutOfBounds()) return ret; auto dmn = tip_mn_list.GetValidMNByCollateral(dsq.masternodeOutpoint); - if (!dmn) return {}; + if (!dmn) return ret; if (dsq.m_protxHash.IsNull()) { dsq.m_protxHash = dmn->proTxHash; } if (!dsq.CheckSignature(dmn->pdmnState->pubKeyOperator.Get())) { - return tl::unexpected{10}; + ret.m_error = MisbehavingError{10}; + return ret; } if (!dsq.fReady) { @@ -173,18 +174,18 @@ PeerMsgRet CCoinJoinServer::ProcessDSQUEUE(const CNode& peer, CDataStream& vRecv //don't allow a few nodes to dominate the queuing process if (nLastDsq != 0 && nDsqThreshold > m_mn_metaman.GetDsqCount()) { LogPrint(BCLog::COINJOIN, "DSQUEUE -- node sending too many dsq messages, masternode=%s\n", dmn->proTxHash.ToString()); - return {}; + return ret; } m_mn_metaman.AllowMixing(dmn->proTxHash); LogPrint(BCLog::COINJOIN, "DSQUEUE -- new CoinJoin queue, masternode=%s, queue=%s\n", dmn->proTxHash.ToString(), dsq.ToString()); TRY_LOCK(cs_vecqueue, lockRecv); - if (!lockRecv) return {}; + if (!lockRecv) return ret; vecCoinJoinQueue.push_back(dsq); m_peerman->RelayDSQ(dsq); } - return {}; + return ret; } void CCoinJoinServer::ProcessDSVIN(CNode& peer, CDataStream& vRecv) diff --git a/src/coinjoin/server.h b/src/coinjoin/server.h index c0611fc4c882..eee182fb9230 100644 --- a/src/coinjoin/server.h +++ b/src/coinjoin/server.h @@ -7,6 +7,7 @@ #include +#include #include class CActiveMasternodeManager; @@ -85,7 +86,7 @@ class CCoinJoinServer : public CCoinJoinBaseSession, public CCoinJoinBaseManager void RelayCompletedTransaction(PoolMessage nMessageID) EXCLUSIVE_LOCKS_REQUIRED(!cs_coinjoin); void ProcessDSACCEPT(CNode& peer, CDataStream& vRecv) EXCLUSIVE_LOCKS_REQUIRED(!cs_vecqueue); - PeerMsgRet ProcessDSQUEUE(const CNode& peer, CDataStream& vRecv) EXCLUSIVE_LOCKS_REQUIRED(!cs_vecqueue); + [[nodiscard]] MessageProcessingResult ProcessDSQUEUE(NodeId from, CDataStream& vRecv) EXCLUSIVE_LOCKS_REQUIRED(!cs_vecqueue); void ProcessDSVIN(CNode& peer, CDataStream& vRecv) EXCLUSIVE_LOCKS_REQUIRED(!cs_coinjoin); void ProcessDSSIGNFINALTX(CDataStream& vRecv) EXCLUSIVE_LOCKS_REQUIRED(!cs_coinjoin); @@ -110,7 +111,7 @@ class CCoinJoinServer : public CCoinJoinBaseSession, public CCoinJoinBaseManager fUnitTest(false) {} - PeerMsgRet ProcessMessage(CNode& pfrom, std::string_view msg_type, CDataStream& vRecv); + [[nodiscard]] MessageProcessingResult ProcessMessage(CNode& pfrom, std::string_view msg_type, CDataStream& vRecv); bool HasTimedOut() const; void CheckTimeout(); diff --git a/src/coinjoin/util.cpp b/src/coinjoin/util.cpp index 7b777c0311b8..dd4c27281217 100644 --- a/src/coinjoin/util.cpp +++ b/src/coinjoin/util.cpp @@ -29,7 +29,9 @@ inline unsigned int GetSizeOfCompactSizeDiff(uint64_t nSizePrev, uint64_t nSizeN CKeyHolder::CKeyHolder(CWallet* pwallet) : reserveDestination(pwallet) { - reserveDestination.GetReservedDestination(dest, false); + auto dest_opt = reserveDestination.GetReservedDestination(false); + assert(dest_opt); + dest = *dest_opt; } void CKeyHolder::KeepKey() @@ -99,10 +101,10 @@ CTransactionBuilderOutput::CTransactionBuilderOutput(CTransactionBuilder* pTxBui nAmount(nAmountIn) { assert(pTxBuilder); - CTxDestination txdest; LOCK(wallet.cs_wallet); - dest.GetReservedDestination(txdest, false); - script = ::GetScriptForDestination(txdest); + auto dest_opt = dest.GetReservedDestination(false); + assert(dest_opt); + script = ::GetScriptForDestination(*dest_opt); } bool CTransactionBuilderOutput::UpdateAmount(const CAmount nNewAmount) @@ -280,12 +282,13 @@ bool CTransactionBuilder::Commit(bilingual_str& strResult) CTransactionRef tx; { LOCK2(m_wallet.cs_wallet, ::cs_main); - FeeCalculation fee_calc_out; - if (auto txr = wallet::CreateTransaction(m_wallet, vecSend, nChangePosRet, strResult, coinControl, fee_calc_out)) { - tx = txr->tx; - nFeeRet = txr->fee; - nChangePosRet = txr->change_pos; + auto ret = wallet::CreateTransaction(m_wallet, vecSend, nChangePosRet, coinControl); + if (ret) { + tx = ret->tx; + nFeeRet = ret->fee; + nChangePosRet = ret->change_pos; } else { + strResult = util::ErrorString(ret); return false; } } diff --git a/src/crypto/x11/blake.c b/src/crypto/x11/blake.c index c7624cfdfb8d..cdd4589974d2 100644 --- a/src/crypto/x11/blake.c +++ b/src/crypto/x11/blake.c @@ -43,7 +43,7 @@ extern "C"{ #define SPH_SMALL_FOOTPRINT_BLAKE 1 #endif -#if SPH_64 && (SPH_SMALL_FOOTPRINT_BLAKE || !SPH_64_TRUE) +#if SPH_SMALL_FOOTPRINT_BLAKE #define SPH_COMPACT_BLAKE_64 1 #endif @@ -51,8 +51,6 @@ extern "C"{ #pragma warning (disable: 4146) #endif -#if SPH_64 - static const sph_u64 IV512[8] = { SPH_C64(0x6A09E667F3BCC908), SPH_C64(0xBB67AE8584CAA73B), SPH_C64(0x3C6EF372FE94F82B), SPH_C64(0xA54FF53A5F1D36F1), @@ -60,8 +58,6 @@ static const sph_u64 IV512[8] = { SPH_C64(0x1F83D9ABFB41BD6B), SPH_C64(0x5BE0CD19137E2179) }; -#endif - #if SPH_COMPACT_BLAKE_64 static const unsigned sigma[16][16] = { @@ -271,8 +267,6 @@ static const unsigned sigma[16][16] = { #define Mx_(n) Mx__(n) #define Mx__(n) M ## n -#if SPH_64 - #define CBx(r, i) CBx_(Z ## r ## i) #define CBx_(n) CBx__(n) #define CBx__(n) CB ## n @@ -309,10 +303,6 @@ static const sph_u64 CB[16] = { #endif -#endif - -#if SPH_64 - #define GB(m0, m1, c0, c1, a, b, c, d) do { \ a = SPH_T64(a + b + (m0 ^ c1)); \ d = SPH_ROTR64(d ^ a, 32); \ @@ -360,10 +350,6 @@ static const sph_u64 CB[16] = { #endif -#endif - -#if SPH_64 - #define DECL_STATE64 \ sph_u64 H0, H1, H2, H3, H4, H5, H6, H7; \ sph_u64 S0, S1, S2, S3, T0, T1; @@ -520,10 +506,6 @@ static const sph_u64 CB[16] = { #endif -#endif - -#if SPH_64 - static const sph_u64 salt_zero_big[4] = { 0, 0, 0, 0 }; static void @@ -627,10 +609,6 @@ blake64_close(sph_blake_big_context *sc, sph_enc64be(out + (k << 3), sc->H[k]); } -#endif - -#if SPH_64 - /* see sph_blake.h */ void sph_blake512_init(void *cc) @@ -660,8 +638,6 @@ sph_blake512_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst) sph_blake512_init(cc); } -#endif - #ifdef __cplusplus } #endif diff --git a/src/crypto/x11/bmw.c b/src/crypto/x11/bmw.c index 26134c7966f9..5a7455d18587 100644 --- a/src/crypto/x11/bmw.c +++ b/src/crypto/x11/bmw.c @@ -47,8 +47,6 @@ extern "C"{ #pragma warning (disable: 4146) #endif -#if SPH_64 - static const sph_u64 IV512[] = { SPH_C64(0x8081828384858687), SPH_C64(0x88898A8B8C8D8E8F), SPH_C64(0x9091929394959697), SPH_C64(0x98999A9B9C9D9E9F), @@ -60,11 +58,6 @@ static const sph_u64 IV512[] = { SPH_C64(0xF0F1F2F3F4F5F6F7), SPH_C64(0xF8F9FAFBFCFDFEFF) }; -#endif - -#define XCAT(x, y) XCAT_(x, y) -#define XCAT_(x, y) x ## y - #define LPAR ( #define I16_16 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 @@ -125,38 +118,6 @@ static const sph_u64 IV512[] = { (SPH_T32(SPH_ROTL32(mf(j0m), j1m) + SPH_ROTL32(mf(j3m), j4m) \ - SPH_ROTL32(mf(j10m), j11m) + Ks(j16)) ^ hf(j7m)) -#define expand1s_inner(qf, mf, hf, i16, \ - i0, i1, i2, i3, i4, i5, i6, i7, i8, \ - i9, i10, i11, i12, i13, i14, i15, \ - i0m, i1m, i3m, i4m, i7m, i10m, i11m) \ - SPH_T32(ss1(qf(i0)) + ss2(qf(i1)) + ss3(qf(i2)) + ss0(qf(i3)) \ - + ss1(qf(i4)) + ss2(qf(i5)) + ss3(qf(i6)) + ss0(qf(i7)) \ - + ss1(qf(i8)) + ss2(qf(i9)) + ss3(qf(i10)) + ss0(qf(i11)) \ - + ss1(qf(i12)) + ss2(qf(i13)) + ss3(qf(i14)) + ss0(qf(i15)) \ - + add_elt_s(mf, hf, i0m, i1m, i3m, i4m, i7m, i10m, i11m, i16)) - -#define expand1s(qf, mf, hf, i16) \ - expand1s_(qf, mf, hf, i16, I16_ ## i16, M16_ ## i16) -#define expand1s_(qf, mf, hf, i16, ix, iy) \ - expand1s_inner LPAR qf, mf, hf, i16, ix, iy) - -#define expand2s_inner(qf, mf, hf, i16, \ - i0, i1, i2, i3, i4, i5, i6, i7, i8, \ - i9, i10, i11, i12, i13, i14, i15, \ - i0m, i1m, i3m, i4m, i7m, i10m, i11m) \ - SPH_T32(qf(i0) + rs1(qf(i1)) + qf(i2) + rs2(qf(i3)) \ - + qf(i4) + rs3(qf(i5)) + qf(i6) + rs4(qf(i7)) \ - + qf(i8) + rs5(qf(i9)) + qf(i10) + rs6(qf(i11)) \ - + qf(i12) + rs7(qf(i13)) + ss4(qf(i14)) + ss5(qf(i15)) \ - + add_elt_s(mf, hf, i0m, i1m, i3m, i4m, i7m, i10m, i11m, i16)) - -#define expand2s(qf, mf, hf, i16) \ - expand2s_(qf, mf, hf, i16, I16_ ## i16, M16_ ## i16) -#define expand2s_(qf, mf, hf, i16, ix, iy) \ - expand2s_inner LPAR qf, mf, hf, i16, ix, iy) - -#if SPH_64 - #define sb0(x) (((x) >> 1) ^ SPH_T64((x) << 3) \ ^ SPH_ROTL64(x, 4) ^ SPH_ROTL64(x, 37)) #define sb1(x) (((x) >> 1) ^ SPH_T64((x) << 2) \ @@ -251,14 +212,10 @@ static const sph_u64 Kb_tab[] = { #endif -#endif - #define MAKE_W(tt, i0, op01, i1, op12, i2, op23, i3, op34, i4) \ tt((M(i0) ^ H(i0)) op01 (M(i1) ^ H(i1)) op12 (M(i2) ^ H(i2)) \ op23 (M(i3) ^ H(i3)) op34 (M(i4) ^ H(i4))) -#if SPH_64 - #define Wb0 MAKE_W(SPH_T64, 5, -, 7, +, 10, +, 13, +, 14) #define Wb1 MAKE_W(SPH_T64, 6, -, 8, +, 11, +, 14, -, 15) #define Wb2 MAKE_W(SPH_T64, 0, +, 7, +, 9, -, 12, +, 15) @@ -364,8 +321,6 @@ static const sph_u64 Kb_tab[] = { #define Qb(j) (qt[j]) -#endif - #define FOLD(type, mkQ, tt, rol, mf, qf, dhf) do { \ type qt[32], xl, xh; \ mkQ; \ @@ -407,14 +362,8 @@ static const sph_u64 Kb_tab[] = { + ((xl >> 2) ^ qf(22) ^ qf(15))); \ } while (0) -#if SPH_64 - #define FOLDb FOLD(sph_u64, MAKE_Qb, SPH_T64, SPH_ROTL64, M, Qb, dH) -#endif - -#if SPH_64 - static void compress_big(const unsigned char *data, const sph_u64 h[16], sph_u64 dh[16]) { @@ -540,10 +489,6 @@ bmw64_close(sph_bmw_big_context *sc, unsigned ub, unsigned n, sph_enc64le(out + 8 * u, h1[v]); } -#endif - -#if SPH_64 - /* see sph_bmw.h */ void sph_bmw512_init(void *cc) @@ -573,8 +518,6 @@ sph_bmw512_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst) sph_bmw512_init(cc); } -#endif - #ifdef __cplusplus } #endif diff --git a/src/crypto/x11/echo.c b/src/crypto/x11/echo.c index f0c95f08ab95..ab531bdca5cf 100644 --- a/src/crypto/x11/echo.c +++ b/src/crypto/x11/echo.c @@ -43,36 +43,18 @@ extern "C"{ #define SPH_SMALL_FOOTPRINT_ECHO 1 #endif -/* - * Some measures tend to show that the 64-bit implementation offers - * better performance only on a "64-bit architectures", those which have - * actual 64-bit registers. - */ -#if !defined SPH_ECHO_64 && SPH_64_TRUE -#define SPH_ECHO_64 1 -#endif - /* * We can use a 64-bit implementation only if a 64-bit type is available. */ -#if !SPH_64 -#undef SPH_ECHO_64 -#endif - #ifdef _MSC_VER #pragma warning (disable: 4146) #endif #define T32 SPH_T32 -#define C32 SPH_C32 -#if SPH_64 #define C64 SPH_C64 -#endif #include "aes_helper.c" -#if SPH_ECHO_64 - #define DECL_STATE_BIG \ sph_u64 W[16][2]; @@ -300,253 +282,6 @@ mix_column(sph_u64 W[16][2], int ia, int ib, int ic, int id) FINAL_BIG; \ } while (0) -#else - -#define DECL_STATE_BIG \ - sph_u32 W[16][4]; - -#define INPUT_BLOCK_BIG(sc) do { \ - unsigned u; \ - memcpy(W, sc->u.Vs, 32 * sizeof(sph_u32)); \ - for (u = 0; u < 8; u ++) { \ - W[u + 8][0] = sph_dec32le_aligned( \ - sc->buf + 16 * u); \ - W[u + 8][1] = sph_dec32le_aligned( \ - sc->buf + 16 * u + 4); \ - W[u + 8][2] = sph_dec32le_aligned( \ - sc->buf + 16 * u + 8); \ - W[u + 8][3] = sph_dec32le_aligned( \ - sc->buf + 16 * u + 12); \ - } \ - } while (0) - -#if SPH_SMALL_FOOTPRINT_ECHO - -static void -aes_2rounds_all(sph_u32 W[16][4], - sph_u32 *pK0, sph_u32 *pK1, sph_u32 *pK2, sph_u32 *pK3) -{ - int n; - sph_u32 K0 = *pK0; - sph_u32 K1 = *pK1; - sph_u32 K2 = *pK2; - sph_u32 K3 = *pK3; - - for (n = 0; n < 16; n ++) { - sph_u32 *X = W[n]; - sph_u32 Y0, Y1, Y2, Y3; - AES_ROUND_LE(X[0], X[1], X[2], X[3], - K0, K1, K2, K3, Y0, Y1, Y2, Y3); - AES_ROUND_NOKEY_LE(Y0, Y1, Y2, Y3, X[0], X[1], X[2], X[3]); - if ((K0 = T32(K0 + 1)) == 0) { - if ((K1 = T32(K1 + 1)) == 0) - if ((K2 = T32(K2 + 1)) == 0) - K3 = T32(K3 + 1); - } - } - *pK0 = K0; - *pK1 = K1; - *pK2 = K2; - *pK3 = K3; -} - -#define BIG_SUB_WORDS do { \ - aes_2rounds_all(W, &K0, &K1, &K2, &K3); \ - } while (0) - -#else - -#define AES_2ROUNDS(X) do { \ - sph_u32 Y0, Y1, Y2, Y3; \ - AES_ROUND_LE(X[0], X[1], X[2], X[3], \ - K0, K1, K2, K3, Y0, Y1, Y2, Y3); \ - AES_ROUND_NOKEY_LE(Y0, Y1, Y2, Y3, X[0], X[1], X[2], X[3]); \ - if ((K0 = T32(K0 + 1)) == 0) { \ - if ((K1 = T32(K1 + 1)) == 0) \ - if ((K2 = T32(K2 + 1)) == 0) \ - K3 = T32(K3 + 1); \ - } \ - } while (0) - -#define BIG_SUB_WORDS do { \ - AES_2ROUNDS(W[ 0]); \ - AES_2ROUNDS(W[ 1]); \ - AES_2ROUNDS(W[ 2]); \ - AES_2ROUNDS(W[ 3]); \ - AES_2ROUNDS(W[ 4]); \ - AES_2ROUNDS(W[ 5]); \ - AES_2ROUNDS(W[ 6]); \ - AES_2ROUNDS(W[ 7]); \ - AES_2ROUNDS(W[ 8]); \ - AES_2ROUNDS(W[ 9]); \ - AES_2ROUNDS(W[10]); \ - AES_2ROUNDS(W[11]); \ - AES_2ROUNDS(W[12]); \ - AES_2ROUNDS(W[13]); \ - AES_2ROUNDS(W[14]); \ - AES_2ROUNDS(W[15]); \ - } while (0) - -#endif - -#define SHIFT_ROW1(a, b, c, d) do { \ - sph_u32 tmp; \ - tmp = W[a][0]; \ - W[a][0] = W[b][0]; \ - W[b][0] = W[c][0]; \ - W[c][0] = W[d][0]; \ - W[d][0] = tmp; \ - tmp = W[a][1]; \ - W[a][1] = W[b][1]; \ - W[b][1] = W[c][1]; \ - W[c][1] = W[d][1]; \ - W[d][1] = tmp; \ - tmp = W[a][2]; \ - W[a][2] = W[b][2]; \ - W[b][2] = W[c][2]; \ - W[c][2] = W[d][2]; \ - W[d][2] = tmp; \ - tmp = W[a][3]; \ - W[a][3] = W[b][3]; \ - W[b][3] = W[c][3]; \ - W[c][3] = W[d][3]; \ - W[d][3] = tmp; \ - } while (0) - -#define SHIFT_ROW2(a, b, c, d) do { \ - sph_u32 tmp; \ - tmp = W[a][0]; \ - W[a][0] = W[c][0]; \ - W[c][0] = tmp; \ - tmp = W[b][0]; \ - W[b][0] = W[d][0]; \ - W[d][0] = tmp; \ - tmp = W[a][1]; \ - W[a][1] = W[c][1]; \ - W[c][1] = tmp; \ - tmp = W[b][1]; \ - W[b][1] = W[d][1]; \ - W[d][1] = tmp; \ - tmp = W[a][2]; \ - W[a][2] = W[c][2]; \ - W[c][2] = tmp; \ - tmp = W[b][2]; \ - W[b][2] = W[d][2]; \ - W[d][2] = tmp; \ - tmp = W[a][3]; \ - W[a][3] = W[c][3]; \ - W[c][3] = tmp; \ - tmp = W[b][3]; \ - W[b][3] = W[d][3]; \ - W[d][3] = tmp; \ - } while (0) - -#define SHIFT_ROW3(a, b, c, d) SHIFT_ROW1(d, c, b, a) - -#define BIG_SHIFT_ROWS do { \ - SHIFT_ROW1(1, 5, 9, 13); \ - SHIFT_ROW2(2, 6, 10, 14); \ - SHIFT_ROW3(3, 7, 11, 15); \ - } while (0) - -#if SPH_SMALL_FOOTPRINT_ECHO - -static void -mix_column(sph_u32 W[16][4], int ia, int ib, int ic, int id) -{ - int n; - - for (n = 0; n < 4; n ++) { - sph_u32 a = W[ia][n]; - sph_u32 b = W[ib][n]; - sph_u32 c = W[ic][n]; - sph_u32 d = W[id][n]; - sph_u32 ab = a ^ b; - sph_u32 bc = b ^ c; - sph_u32 cd = c ^ d; - sph_u32 abx = ((ab & C32(0x80808080)) >> 7) * 27U - ^ ((ab & C32(0x7F7F7F7F)) << 1); - sph_u32 bcx = ((bc & C32(0x80808080)) >> 7) * 27U - ^ ((bc & C32(0x7F7F7F7F)) << 1); - sph_u32 cdx = ((cd & C32(0x80808080)) >> 7) * 27U - ^ ((cd & C32(0x7F7F7F7F)) << 1); - W[ia][n] = abx ^ bc ^ d; - W[ib][n] = bcx ^ a ^ cd; - W[ic][n] = cdx ^ ab ^ d; - W[id][n] = abx ^ bcx ^ cdx ^ ab ^ c; - } -} - -#define MIX_COLUMN(a, b, c, d) mix_column(W, a, b, c, d) - -#else - -#define MIX_COLUMN1(ia, ib, ic, id, n) do { \ - sph_u32 a = W[ia][n]; \ - sph_u32 b = W[ib][n]; \ - sph_u32 c = W[ic][n]; \ - sph_u32 d = W[id][n]; \ - sph_u32 ab = a ^ b; \ - sph_u32 bc = b ^ c; \ - sph_u32 cd = c ^ d; \ - sph_u32 abx = ((ab & C32(0x80808080)) >> 7) * 27U \ - ^ ((ab & C32(0x7F7F7F7F)) << 1); \ - sph_u32 bcx = ((bc & C32(0x80808080)) >> 7) * 27U \ - ^ ((bc & C32(0x7F7F7F7F)) << 1); \ - sph_u32 cdx = ((cd & C32(0x80808080)) >> 7) * 27U \ - ^ ((cd & C32(0x7F7F7F7F)) << 1); \ - W[ia][n] = abx ^ bc ^ d; \ - W[ib][n] = bcx ^ a ^ cd; \ - W[ic][n] = cdx ^ ab ^ d; \ - W[id][n] = abx ^ bcx ^ cdx ^ ab ^ c; \ - } while (0) - -#define MIX_COLUMN(a, b, c, d) do { \ - MIX_COLUMN1(a, b, c, d, 0); \ - MIX_COLUMN1(a, b, c, d, 1); \ - MIX_COLUMN1(a, b, c, d, 2); \ - MIX_COLUMN1(a, b, c, d, 3); \ - } while (0) - -#endif - -#define BIG_MIX_COLUMNS do { \ - MIX_COLUMN(0, 1, 2, 3); \ - MIX_COLUMN(4, 5, 6, 7); \ - MIX_COLUMN(8, 9, 10, 11); \ - MIX_COLUMN(12, 13, 14, 15); \ - } while (0) - -#define BIG_ROUND do { \ - BIG_SUB_WORDS; \ - BIG_SHIFT_ROWS; \ - BIG_MIX_COLUMNS; \ - } while (0) - -#define FINAL_BIG do { \ - unsigned u; \ - sph_u32 *VV = &sc->u.Vs[0][0]; \ - sph_u32 *WW = &W[0][0]; \ - for (u = 0; u < 32; u ++) { \ - VV[u] ^= sph_dec32le_aligned(sc->buf + (u * 4)) \ - ^ WW[u] ^ WW[u + 32]; \ - } \ - } while (0) - -#define COMPRESS_BIG(sc) do { \ - sph_u32 K0 = sc->C0; \ - sph_u32 K1 = sc->C1; \ - sph_u32 K2 = sc->C2; \ - sph_u32 K3 = sc->C3; \ - unsigned u; \ - INPUT_BLOCK_BIG(sc); \ - for (u = 0; u < 10; u ++) { \ - BIG_ROUND; \ - } \ - FINAL_BIG; \ - } while (0) - -#endif #define INCR_COUNTER(sc, val) do { \ sc->C0 = T32(sc->C0 + (sph_u32)(val)); \ @@ -560,7 +295,6 @@ mix_column(sph_u32 W[16][4], int ia, int ib, int ic, int id) static void echo_big_init(sph_echo_big_context *sc, unsigned out_len) { -#if SPH_ECHO_64 sc->u.Vb[0][0] = (sph_u64)out_len; sc->u.Vb[0][1] = 0; sc->u.Vb[1][0] = (sph_u64)out_len; @@ -577,24 +311,6 @@ echo_big_init(sph_echo_big_context *sc, unsigned out_len) sc->u.Vb[6][1] = 0; sc->u.Vb[7][0] = (sph_u64)out_len; sc->u.Vb[7][1] = 0; -#else - sc->u.Vs[0][0] = (sph_u32)out_len; - sc->u.Vs[0][1] = sc->u.Vs[0][2] = sc->u.Vs[0][3] = 0; - sc->u.Vs[1][0] = (sph_u32)out_len; - sc->u.Vs[1][1] = sc->u.Vs[1][2] = sc->u.Vs[1][3] = 0; - sc->u.Vs[2][0] = (sph_u32)out_len; - sc->u.Vs[2][1] = sc->u.Vs[2][2] = sc->u.Vs[2][3] = 0; - sc->u.Vs[3][0] = (sph_u32)out_len; - sc->u.Vs[3][1] = sc->u.Vs[3][2] = sc->u.Vs[3][3] = 0; - sc->u.Vs[4][0] = (sph_u32)out_len; - sc->u.Vs[4][1] = sc->u.Vs[4][2] = sc->u.Vs[4][3] = 0; - sc->u.Vs[5][0] = (sph_u32)out_len; - sc->u.Vs[5][1] = sc->u.Vs[5][2] = sc->u.Vs[5][3] = 0; - sc->u.Vs[6][0] = (sph_u32)out_len; - sc->u.Vs[6][1] = sc->u.Vs[6][2] = sc->u.Vs[6][3] = 0; - sc->u.Vs[7][0] = (sph_u32)out_len; - sc->u.Vs[7][1] = sc->u.Vs[7][2] = sc->u.Vs[7][3] = 0; -#endif sc->ptr = 0; sc->C0 = sc->C1 = sc->C2 = sc->C3 = 0; } @@ -653,15 +369,9 @@ echo_big_close(sph_echo_big_context *sc, unsigned ub, unsigned n, union { unsigned char tmp[64]; sph_u32 dummy; -#if SPH_ECHO_64 sph_u64 dummy2; -#endif } u; -#if SPH_ECHO_64 sph_u64 *VV; -#else - sph_u32 *VV; -#endif unsigned k; buf = sc->buf; @@ -690,13 +400,8 @@ echo_big_close(sph_echo_big_context *sc, unsigned ub, unsigned n, sph_enc16le(buf + (sizeof sc->buf) - 18, out_size_w32 << 5); memcpy(buf + (sizeof sc->buf) - 16, u.tmp, 16); echo_big_compress(sc); -#if SPH_ECHO_64 for (VV = &sc->u.Vb[0][0], k = 0; k < ((out_size_w32 + 1) >> 1); k ++) sph_enc64le_aligned(u.tmp + (k << 3), VV[k]); -#else - for (VV = &sc->u.Vs[0][0], k = 0; k < out_size_w32; k ++) - sph_enc32le_aligned(u.tmp + (k << 2), VV[k]); -#endif memcpy(dst, u.tmp, out_size_w32 << 2); echo_big_init(sc, out_size_w32 << 5); } diff --git a/src/crypto/x11/groestl.c b/src/crypto/x11/groestl.c index b010e456e73b..24c31c340949 100644 --- a/src/crypto/x11/groestl.c +++ b/src/crypto/x11/groestl.c @@ -43,22 +43,6 @@ extern "C"{ #define SPH_SMALL_FOOTPRINT_GROESTL 1 #endif -/* - * Apparently, the 32-bit-only version is not faster than the 64-bit - * version unless using the "small footprint" code on a 32-bit machine. - */ -#if !defined SPH_GROESTL_64 -#if SPH_SMALL_FOOTPRINT_GROESTL && !SPH_64_TRUE -#define SPH_GROESTL_64 0 -#else -#define SPH_GROESTL_64 1 -#endif -#endif - -#if !SPH_64 -#undef SPH_GROESTL_64 -#endif - #ifdef _MSC_VER #pragma warning (disable: 4146) #endif @@ -85,7 +69,6 @@ extern "C"{ | ((SPH_C32(x) << 8) & SPH_C32(0x00FF0000)) \ | ((SPH_C32(x) << 24) & SPH_C32(0xFF000000))) #define dec32e_aligned sph_dec32le_aligned -#define enc32e sph_enc32le #define B32_0(x) ((x) & 0xFF) #define B32_1(x) (((x) >> 8) & 0xFF) #define B32_2(x) (((x) >> 16) & 0xFF) @@ -99,7 +82,6 @@ extern "C"{ #define QC32up(j, r) SPH_C32(0xFFFFFFFF) #define QC32dn(j, r) (((sph_u32)(r) << 24) ^ SPH_T32(~((sph_u32)(j) << 24))) -#if SPH_64 #define C64e(x) ((SPH_C64(x) >> 56) \ | ((SPH_C64(x) >> 40) & SPH_C64(0x000000000000FF00)) \ | ((SPH_C64(x) >> 24) & SPH_C64(0x0000000000FF0000)) \ @@ -121,13 +103,11 @@ extern "C"{ #define R64 SPH_ROTL64 #define PC64(j, r) ((sph_u64)((j) + (r))) #define QC64(j, r) (((sph_u64)(r) << 56) ^ SPH_T64(~((sph_u64)(j) << 56))) -#endif #else #define C32e(x) SPH_C32(x) #define dec32e_aligned sph_dec32be_aligned -#define enc32e sph_enc32be #define B32_0(x) ((x) >> 24) #define B32_1(x) (((x) >> 16) & 0xFF) #define B32_2(x) (((x) >> 8) & 0xFF) @@ -141,7 +121,6 @@ extern "C"{ #define QC32up(j, r) SPH_C32(0xFFFFFFFF) #define QC32dn(j, r) ((sph_u32)(r) ^ SPH_T32(~(sph_u32)(j))) -#if SPH_64 #define C64e(x) SPH_C64(x) #define dec64e_aligned sph_dec64be_aligned #define enc64e sph_enc64be @@ -156,12 +135,9 @@ extern "C"{ #define R64 SPH_ROTR64 #define PC64(j, r) ((sph_u64)((j) + (r)) << 56) #define QC64(j, r) ((sph_u64)(r) ^ SPH_T64(~(sph_u64)(j))) -#endif #endif -#if SPH_GROESTL_64 - static const sph_u64 T0[] = { C64e(0xc632f4a5f497a5c6), C64e(0xf86f978497eb84f8), C64e(0xee5eb099b0c799ee), C64e(0xf67a8c8d8cf78df6), @@ -688,8 +664,6 @@ static const sph_u64 T3[] = { C64e(0xdad66d6d0c61d661), C64e(0x583a2c2c624e3a4e) }; -#endif - static const sph_u64 T4[] = { C64e(0xf497a5c6c632f4a5), C64e(0x97eb84f8f86f9784), C64e(0xb0c799eeee5eb099), C64e(0x8cf78df6f67a8c8d), @@ -1218,34 +1192,6 @@ static const sph_u64 T7[] = { #endif -#if SPH_SMALL_FOOTPRINT_GROESTL - -#define RSTT(d, a, b0, b1, b2, b3, b4, b5, b6, b7) do { \ - t[d] = T0[B64_0(a[b0])] \ - ^ R64(T0[B64_1(a[b1])], 8) \ - ^ R64(T0[B64_2(a[b2])], 16) \ - ^ R64(T0[B64_3(a[b3])], 24) \ - ^ T4[B64_4(a[b4])] \ - ^ R64(T4[B64_5(a[b5])], 8) \ - ^ R64(T4[B64_6(a[b6])], 16) \ - ^ R64(T4[B64_7(a[b7])], 24); \ - } while (0) - -#else - -#define RSTT(d, a, b0, b1, b2, b3, b4, b5, b6, b7) do { \ - t[d] = T0[B64_0(a[b0])] \ - ^ T1[B64_1(a[b1])] \ - ^ T2[B64_2(a[b2])] \ - ^ T3[B64_3(a[b3])] \ - ^ T4[B64_4(a[b4])] \ - ^ T5[B64_5(a[b5])] \ - ^ T6[B64_6(a[b6])] \ - ^ T7[B64_7(a[b7])]; \ - } while (0) - -#endif - #define DECL_STATE_BIG \ sph_u64 H[16]; @@ -2044,28 +1990,6 @@ static const sph_u32 T3dn[] = { C32e(0x3d46cb46), C32e(0xb71ffc1f), C32e(0x0c61d661), C32e(0x624e3a4e) }; -#define XCAT(x, y) XCAT_(x, y) -#define XCAT_(x, y) x ## y - -#define RSTT(d0, d1, a, b0, b1, b2, b3, b4, b5, b6, b7) do { \ - t[d0] = T0up[B32_0(a[b0])] \ - ^ T1up[B32_1(a[b1])] \ - ^ T2up[B32_2(a[b2])] \ - ^ T3up[B32_3(a[b3])] \ - ^ T0dn[B32_0(a[b4])] \ - ^ T1dn[B32_1(a[b5])] \ - ^ T2dn[B32_2(a[b6])] \ - ^ T3dn[B32_3(a[b7])]; \ - t[d1] = T0dn[B32_0(a[b0])] \ - ^ T1dn[B32_1(a[b1])] \ - ^ T2dn[B32_2(a[b2])] \ - ^ T3dn[B32_3(a[b3])] \ - ^ T0up[B32_0(a[b4])] \ - ^ T1up[B32_1(a[b5])] \ - ^ T2up[B32_2(a[b6])] \ - ^ T3up[B32_3(a[b7])]; \ - } while (0) - #define DECL_STATE_BIG \ sph_u32 H[32]; @@ -2457,7 +2381,6 @@ groestl_big_init(sph_groestl_big_context *sc, unsigned out_size) size_t u; sc->ptr = 0; -#if SPH_GROESTL_64 for (u = 0; u < 15; u ++) sc->state.wide[u] = 0; #if USE_LE @@ -2466,22 +2389,7 @@ groestl_big_init(sph_groestl_big_context *sc, unsigned out_size) #else sc->state.wide[15] = (sph_u64)out_size; #endif -#else - for (u = 0; u < 31; u ++) - sc->state.narrow[u] = 0; -#if USE_LE - sc->state.narrow[31] = ((sph_u32)(out_size & 0xFF) << 24) - | ((sph_u32)(out_size & 0xFF00) << 8); -#else - sc->state.narrow[31] = (sph_u32)out_size; -#endif -#endif -#if SPH_64 sc->count = 0; -#else - sc->count_high = 0; - sc->count_low = 0; -#endif } static void @@ -2513,12 +2421,7 @@ groestl_big_core(sph_groestl_big_context *sc, const void *data, size_t len) len -= clen; if (ptr == sizeof sc->buf) { COMPRESS_BIG; -#if SPH_64 sc->count ++; -#else - if ((sc->count_low = SPH_T32(sc->count_low + 1)) == 0) - sc->count_high = SPH_T32(sc->count_high + 1); -#endif ptr = 0; } } @@ -2533,11 +2436,7 @@ groestl_big_close(sph_groestl_big_context *sc, unsigned char *buf; unsigned char pad[136]; size_t ptr, pad_len, u; -#if SPH_64 sph_u64 count; -#else - sph_u32 count_high, count_low; -#endif unsigned z; DECL_STATE_BIG @@ -2547,42 +2446,18 @@ groestl_big_close(sph_groestl_big_context *sc, pad[0] = ((ub & -z) | z) & 0xFF; if (ptr < 120) { pad_len = 128 - ptr; -#if SPH_64 count = SPH_T64(sc->count + 1); -#else - count_low = SPH_T32(sc->count_low + 1); - count_high = SPH_T32(sc->count_high); - if (count_low == 0) - count_high = SPH_T32(count_high + 1); -#endif } else { pad_len = 256 - ptr; -#if SPH_64 count = SPH_T64(sc->count + 2); -#else - count_low = SPH_T32(sc->count_low + 2); - count_high = SPH_T32(sc->count_high); - if (count_low <= 1) - count_high = SPH_T32(count_high + 1); -#endif } memset(pad + 1, 0, pad_len - 9); -#if SPH_64 sph_enc64be(pad + pad_len - 8, count); -#else - sph_enc64be(pad + pad_len - 8, count_high); - sph_enc64be(pad + pad_len - 4, count_low); -#endif groestl_big_core(sc, pad, pad_len); READ_STATE_BIG(sc); FINAL_BIG; -#if SPH_GROESTL_64 for (u = 0; u < 8; u ++) enc64e(pad + (u << 3), H[u + 8]); -#else - for (u = 0; u < 16; u ++) - enc32e(pad + (u << 2), H[u + 16]); -#endif memcpy(dst, pad + 64 - out_len, out_len); groestl_big_init(sc, (unsigned)out_len << 3); } diff --git a/src/crypto/x11/jh.c b/src/crypto/x11/jh.c index 6f9136873bd2..85002c7481f3 100644 --- a/src/crypto/x11/jh.c +++ b/src/crypto/x11/jh.c @@ -44,14 +44,6 @@ extern "C"{ #define SPH_SMALL_FOOTPRINT_JH 1 #endif -#if !defined SPH_JH_64 && SPH_64_TRUE -#define SPH_JH_64 1 -#endif - -#if !SPH_64 -#undef SPH_JH_64 -#endif - #ifdef _MSC_VER #pragma warning (disable: 4146) #endif @@ -67,14 +59,6 @@ extern "C"{ #if SPH_LITTLE_ENDIAN -#define C32e(x) ((SPH_C32(x) >> 24) \ - | ((SPH_C32(x) >> 8) & SPH_C32(0x0000FF00)) \ - | ((SPH_C32(x) << 8) & SPH_C32(0x00FF0000)) \ - | ((SPH_C32(x) << 24) & SPH_C32(0xFF000000))) -#define dec32e_aligned sph_dec32le_aligned -#define enc32e sph_enc32le - -#if SPH_64 #define C64e(x) ((SPH_C64(x) >> 56) \ | ((SPH_C64(x) >> 40) & SPH_C64(0x000000000000FF00)) \ | ((SPH_C64(x) >> 24) & SPH_C64(0x0000000000FF0000)) \ @@ -85,18 +69,12 @@ extern "C"{ | ((SPH_C64(x) << 56) & SPH_C64(0xFF00000000000000))) #define dec64e_aligned sph_dec64le_aligned #define enc64e sph_enc64le -#endif #else -#define C32e(x) SPH_C32(x) -#define dec32e_aligned sph_dec32be_aligned -#define enc32e sph_enc32be -#if SPH_64 #define C64e(x) SPH_C64(x) #define dec64e_aligned sph_dec64be_aligned #define enc64e sph_enc64be -#endif #endif @@ -125,8 +103,6 @@ extern "C"{ x3 ^= x4; \ } while (0) -#if SPH_JH_64 - static const sph_u64 C[] = { C64e(0x72d5dea2df15f867), C64e(0x7b84150ab7231557), C64e(0x81abd6904d5a87f6), C64e(0x4e9f4fc5c3d12b40), @@ -332,325 +308,6 @@ static const sph_u64 IV512[] = { C64e(0xe3c2fcdfe68517fb), C64e(0x545a4678cc8cdd4b) }; -#else - -static const sph_u32 C[] = { - C32e(0x72d5dea2), C32e(0xdf15f867), C32e(0x7b84150a), - C32e(0xb7231557), C32e(0x81abd690), C32e(0x4d5a87f6), - C32e(0x4e9f4fc5), C32e(0xc3d12b40), C32e(0xea983ae0), - C32e(0x5c45fa9c), C32e(0x03c5d299), C32e(0x66b2999a), - C32e(0x660296b4), C32e(0xf2bb538a), C32e(0xb556141a), - C32e(0x88dba231), C32e(0x03a35a5c), C32e(0x9a190edb), - C32e(0x403fb20a), C32e(0x87c14410), C32e(0x1c051980), - C32e(0x849e951d), C32e(0x6f33ebad), C32e(0x5ee7cddc), - C32e(0x10ba1392), C32e(0x02bf6b41), C32e(0xdc786515), - C32e(0xf7bb27d0), C32e(0x0a2c8139), C32e(0x37aa7850), - C32e(0x3f1abfd2), C32e(0x410091d3), C32e(0x422d5a0d), - C32e(0xf6cc7e90), C32e(0xdd629f9c), C32e(0x92c097ce), - C32e(0x185ca70b), C32e(0xc72b44ac), C32e(0xd1df65d6), - C32e(0x63c6fc23), C32e(0x976e6c03), C32e(0x9ee0b81a), - C32e(0x2105457e), C32e(0x446ceca8), C32e(0xeef103bb), - C32e(0x5d8e61fa), C32e(0xfd9697b2), C32e(0x94838197), - C32e(0x4a8e8537), C32e(0xdb03302f), C32e(0x2a678d2d), - C32e(0xfb9f6a95), C32e(0x8afe7381), C32e(0xf8b8696c), - C32e(0x8ac77246), C32e(0xc07f4214), C32e(0xc5f4158f), - C32e(0xbdc75ec4), C32e(0x75446fa7), C32e(0x8f11bb80), - C32e(0x52de75b7), C32e(0xaee488bc), C32e(0x82b8001e), - C32e(0x98a6a3f4), C32e(0x8ef48f33), C32e(0xa9a36315), - C32e(0xaa5f5624), C32e(0xd5b7f989), C32e(0xb6f1ed20), - C32e(0x7c5ae0fd), C32e(0x36cae95a), C32e(0x06422c36), - C32e(0xce293543), C32e(0x4efe983d), C32e(0x533af974), - C32e(0x739a4ba7), C32e(0xd0f51f59), C32e(0x6f4e8186), - C32e(0x0e9dad81), C32e(0xafd85a9f), C32e(0xa7050667), - C32e(0xee34626a), C32e(0x8b0b28be), C32e(0x6eb91727), - C32e(0x47740726), C32e(0xc680103f), C32e(0xe0a07e6f), - C32e(0xc67e487b), C32e(0x0d550aa5), C32e(0x4af8a4c0), - C32e(0x91e3e79f), C32e(0x978ef19e), C32e(0x86767281), - C32e(0x50608dd4), C32e(0x7e9e5a41), C32e(0xf3e5b062), - C32e(0xfc9f1fec), C32e(0x4054207a), C32e(0xe3e41a00), - C32e(0xcef4c984), C32e(0x4fd794f5), C32e(0x9dfa95d8), - C32e(0x552e7e11), C32e(0x24c354a5), C32e(0x5bdf7228), - C32e(0xbdfe6e28), C32e(0x78f57fe2), C32e(0x0fa5c4b2), - C32e(0x05897cef), C32e(0xee49d32e), C32e(0x447e9385), - C32e(0xeb28597f), C32e(0x705f6937), C32e(0xb324314a), - C32e(0x5e8628f1), C32e(0x1dd6e465), C32e(0xc71b7704), - C32e(0x51b920e7), C32e(0x74fe43e8), C32e(0x23d4878a), - C32e(0x7d29e8a3), C32e(0x927694f2), C32e(0xddcb7a09), - C32e(0x9b30d9c1), C32e(0x1d1b30fb), C32e(0x5bdc1be0), - C32e(0xda24494f), C32e(0xf29c82bf), C32e(0xa4e7ba31), - C32e(0xb470bfff), C32e(0x0d324405), C32e(0xdef8bc48), - C32e(0x3baefc32), C32e(0x53bbd339), C32e(0x459fc3c1), - C32e(0xe0298ba0), C32e(0xe5c905fd), C32e(0xf7ae090f), - C32e(0x94703412), C32e(0x4290f134), C32e(0xa271b701), - C32e(0xe344ed95), C32e(0xe93b8e36), C32e(0x4f2f984a), - C32e(0x88401d63), C32e(0xa06cf615), C32e(0x47c1444b), - C32e(0x8752afff), C32e(0x7ebb4af1), C32e(0xe20ac630), - C32e(0x4670b6c5), C32e(0xcc6e8ce6), C32e(0xa4d5a456), - C32e(0xbd4fca00), C32e(0xda9d844b), C32e(0xc83e18ae), - C32e(0x7357ce45), C32e(0x3064d1ad), C32e(0xe8a6ce68), - C32e(0x145c2567), C32e(0xa3da8cf2), C32e(0xcb0ee116), - C32e(0x33e90658), C32e(0x9a94999a), C32e(0x1f60b220), - C32e(0xc26f847b), C32e(0xd1ceac7f), C32e(0xa0d18518), - C32e(0x32595ba1), C32e(0x8ddd19d3), C32e(0x509a1cc0), - C32e(0xaaa5b446), C32e(0x9f3d6367), C32e(0xe4046bba), - C32e(0xf6ca19ab), C32e(0x0b56ee7e), C32e(0x1fb179ea), - C32e(0xa9282174), C32e(0xe9bdf735), C32e(0x3b3651ee), - C32e(0x1d57ac5a), C32e(0x7550d376), C32e(0x3a46c2fe), - C32e(0xa37d7001), C32e(0xf735c1af), C32e(0x98a4d842), - C32e(0x78edec20), C32e(0x9e6b6779), C32e(0x41836315), - C32e(0xea3adba8), C32e(0xfac33b4d), C32e(0x32832c83), - C32e(0xa7403b1f), C32e(0x1c2747f3), C32e(0x5940f034), - C32e(0xb72d769a), C32e(0xe73e4e6c), C32e(0xd2214ffd), - C32e(0xb8fd8d39), C32e(0xdc5759ef), C32e(0x8d9b0c49), - C32e(0x2b49ebda), C32e(0x5ba2d749), C32e(0x68f3700d), - C32e(0x7d3baed0), C32e(0x7a8d5584), C32e(0xf5a5e9f0), - C32e(0xe4f88e65), C32e(0xa0b8a2f4), C32e(0x36103b53), - C32e(0x0ca8079e), C32e(0x753eec5a), C32e(0x91689492), - C32e(0x56e8884f), C32e(0x5bb05c55), C32e(0xf8babc4c), - C32e(0xe3bb3b99), C32e(0xf387947b), C32e(0x75daf4d6), - C32e(0x726b1c5d), C32e(0x64aeac28), C32e(0xdc34b36d), - C32e(0x6c34a550), C32e(0xb828db71), C32e(0xf861e2f2), - C32e(0x108d512a), C32e(0xe3db6433), C32e(0x59dd75fc), - C32e(0x1cacbcf1), C32e(0x43ce3fa2), C32e(0x67bbd13c), - C32e(0x02e843b0), C32e(0x330a5bca), C32e(0x8829a175), - C32e(0x7f34194d), C32e(0xb416535c), C32e(0x923b94c3), - C32e(0x0e794d1e), C32e(0x797475d7), C32e(0xb6eeaf3f), - C32e(0xeaa8d4f7), C32e(0xbe1a3921), C32e(0x5cf47e09), - C32e(0x4c232751), C32e(0x26a32453), C32e(0xba323cd2), - C32e(0x44a3174a), C32e(0x6da6d5ad), C32e(0xb51d3ea6), - C32e(0xaff2c908), C32e(0x83593d98), C32e(0x916b3c56), - C32e(0x4cf87ca1), C32e(0x7286604d), C32e(0x46e23ecc), - C32e(0x086ec7f6), C32e(0x2f9833b3), C32e(0xb1bc765e), - C32e(0x2bd666a5), C32e(0xefc4e62a), C32e(0x06f4b6e8), - C32e(0xbec1d436), C32e(0x74ee8215), C32e(0xbcef2163), - C32e(0xfdc14e0d), C32e(0xf453c969), C32e(0xa77d5ac4), - C32e(0x06585826), C32e(0x7ec11416), C32e(0x06e0fa16), - C32e(0x7e90af3d), C32e(0x28639d3f), C32e(0xd2c9f2e3), - C32e(0x009bd20c), C32e(0x5faace30), C32e(0xb7d40c30), - C32e(0x742a5116), C32e(0xf2e03298), C32e(0x0deb30d8), - C32e(0xe3cef89a), C32e(0x4bc59e7b), C32e(0xb5f17992), - C32e(0xff51e66e), C32e(0x048668d3), C32e(0x9b234d57), - C32e(0xe6966731), C32e(0xcce6a6f3), C32e(0x170a7505), - C32e(0xb17681d9), C32e(0x13326cce), C32e(0x3c175284), - C32e(0xf805a262), C32e(0xf42bcbb3), C32e(0x78471547), - C32e(0xff465482), C32e(0x23936a48), C32e(0x38df5807), - C32e(0x4e5e6565), C32e(0xf2fc7c89), C32e(0xfc86508e), - C32e(0x31702e44), C32e(0xd00bca86), C32e(0xf04009a2), - C32e(0x3078474e), C32e(0x65a0ee39), C32e(0xd1f73883), - C32e(0xf75ee937), C32e(0xe42c3abd), C32e(0x2197b226), - C32e(0x0113f86f), C32e(0xa344edd1), C32e(0xef9fdee7), - C32e(0x8ba0df15), C32e(0x762592d9), C32e(0x3c85f7f6), - C32e(0x12dc42be), C32e(0xd8a7ec7c), C32e(0xab27b07e), - C32e(0x538d7dda), C32e(0xaa3ea8de), C32e(0xaa25ce93), - C32e(0xbd0269d8), C32e(0x5af643fd), C32e(0x1a7308f9), - C32e(0xc05fefda), C32e(0x174a19a5), C32e(0x974d6633), - C32e(0x4cfd216a), C32e(0x35b49831), C32e(0xdb411570), - C32e(0xea1e0fbb), C32e(0xedcd549b), C32e(0x9ad063a1), - C32e(0x51974072), C32e(0xf6759dbf), C32e(0x91476fe2) -}; - -#define Ceven_w3(r) (C[((r) << 3) + 0]) -#define Ceven_w2(r) (C[((r) << 3) + 1]) -#define Ceven_w1(r) (C[((r) << 3) + 2]) -#define Ceven_w0(r) (C[((r) << 3) + 3]) -#define Codd_w3(r) (C[((r) << 3) + 4]) -#define Codd_w2(r) (C[((r) << 3) + 5]) -#define Codd_w1(r) (C[((r) << 3) + 6]) -#define Codd_w0(r) (C[((r) << 3) + 7]) - -#define S(x0, x1, x2, x3, cb, r) do { \ - Sb(x0 ## 3, x1 ## 3, x2 ## 3, x3 ## 3, cb ## w3(r)); \ - Sb(x0 ## 2, x1 ## 2, x2 ## 2, x3 ## 2, cb ## w2(r)); \ - Sb(x0 ## 1, x1 ## 1, x2 ## 1, x3 ## 1, cb ## w1(r)); \ - Sb(x0 ## 0, x1 ## 0, x2 ## 0, x3 ## 0, cb ## w0(r)); \ - } while (0) - -#define L(x0, x1, x2, x3, x4, x5, x6, x7) do { \ - Lb(x0 ## 3, x1 ## 3, x2 ## 3, x3 ## 3, \ - x4 ## 3, x5 ## 3, x6 ## 3, x7 ## 3); \ - Lb(x0 ## 2, x1 ## 2, x2 ## 2, x3 ## 2, \ - x4 ## 2, x5 ## 2, x6 ## 2, x7 ## 2); \ - Lb(x0 ## 1, x1 ## 1, x2 ## 1, x3 ## 1, \ - x4 ## 1, x5 ## 1, x6 ## 1, x7 ## 1); \ - Lb(x0 ## 0, x1 ## 0, x2 ## 0, x3 ## 0, \ - x4 ## 0, x5 ## 0, x6 ## 0, x7 ## 0); \ - } while (0) - -#define Wz(x, c, n) do { \ - sph_u32 t = (x ## 3 & (c)) << (n); \ - x ## 3 = ((x ## 3 >> (n)) & (c)) | t; \ - t = (x ## 2 & (c)) << (n); \ - x ## 2 = ((x ## 2 >> (n)) & (c)) | t; \ - t = (x ## 1 & (c)) << (n); \ - x ## 1 = ((x ## 1 >> (n)) & (c)) | t; \ - t = (x ## 0 & (c)) << (n); \ - x ## 0 = ((x ## 0 >> (n)) & (c)) | t; \ - } while (0) - -#define W0(x) Wz(x, SPH_C32(0x55555555), 1) -#define W1(x) Wz(x, SPH_C32(0x33333333), 2) -#define W2(x) Wz(x, SPH_C32(0x0F0F0F0F), 4) -#define W3(x) Wz(x, SPH_C32(0x00FF00FF), 8) -#define W4(x) Wz(x, SPH_C32(0x0000FFFF), 16) -#define W5(x) do { \ - sph_u32 t = x ## 3; \ - x ## 3 = x ## 2; \ - x ## 2 = t; \ - t = x ## 1; \ - x ## 1 = x ## 0; \ - x ## 0 = t; \ - } while (0) -#define W6(x) do { \ - sph_u32 t = x ## 3; \ - x ## 3 = x ## 1; \ - x ## 1 = t; \ - t = x ## 2; \ - x ## 2 = x ## 0; \ - x ## 0 = t; \ - } while (0) - -#define DECL_STATE \ - sph_u32 h03, h02, h01, h00, h13, h12, h11, h10; \ - sph_u32 h23, h22, h21, h20, h33, h32, h31, h30; \ - sph_u32 h43, h42, h41, h40, h53, h52, h51, h50; \ - sph_u32 h63, h62, h61, h60, h73, h72, h71, h70; \ - sph_u32 tmp; - -#define READ_STATE(state) do { \ - h03 = (state)->H.narrow[ 0]; \ - h02 = (state)->H.narrow[ 1]; \ - h01 = (state)->H.narrow[ 2]; \ - h00 = (state)->H.narrow[ 3]; \ - h13 = (state)->H.narrow[ 4]; \ - h12 = (state)->H.narrow[ 5]; \ - h11 = (state)->H.narrow[ 6]; \ - h10 = (state)->H.narrow[ 7]; \ - h23 = (state)->H.narrow[ 8]; \ - h22 = (state)->H.narrow[ 9]; \ - h21 = (state)->H.narrow[10]; \ - h20 = (state)->H.narrow[11]; \ - h33 = (state)->H.narrow[12]; \ - h32 = (state)->H.narrow[13]; \ - h31 = (state)->H.narrow[14]; \ - h30 = (state)->H.narrow[15]; \ - h43 = (state)->H.narrow[16]; \ - h42 = (state)->H.narrow[17]; \ - h41 = (state)->H.narrow[18]; \ - h40 = (state)->H.narrow[19]; \ - h53 = (state)->H.narrow[20]; \ - h52 = (state)->H.narrow[21]; \ - h51 = (state)->H.narrow[22]; \ - h50 = (state)->H.narrow[23]; \ - h63 = (state)->H.narrow[24]; \ - h62 = (state)->H.narrow[25]; \ - h61 = (state)->H.narrow[26]; \ - h60 = (state)->H.narrow[27]; \ - h73 = (state)->H.narrow[28]; \ - h72 = (state)->H.narrow[29]; \ - h71 = (state)->H.narrow[30]; \ - h70 = (state)->H.narrow[31]; \ - } while (0) - -#define WRITE_STATE(state) do { \ - (state)->H.narrow[ 0] = h03; \ - (state)->H.narrow[ 1] = h02; \ - (state)->H.narrow[ 2] = h01; \ - (state)->H.narrow[ 3] = h00; \ - (state)->H.narrow[ 4] = h13; \ - (state)->H.narrow[ 5] = h12; \ - (state)->H.narrow[ 6] = h11; \ - (state)->H.narrow[ 7] = h10; \ - (state)->H.narrow[ 8] = h23; \ - (state)->H.narrow[ 9] = h22; \ - (state)->H.narrow[10] = h21; \ - (state)->H.narrow[11] = h20; \ - (state)->H.narrow[12] = h33; \ - (state)->H.narrow[13] = h32; \ - (state)->H.narrow[14] = h31; \ - (state)->H.narrow[15] = h30; \ - (state)->H.narrow[16] = h43; \ - (state)->H.narrow[17] = h42; \ - (state)->H.narrow[18] = h41; \ - (state)->H.narrow[19] = h40; \ - (state)->H.narrow[20] = h53; \ - (state)->H.narrow[21] = h52; \ - (state)->H.narrow[22] = h51; \ - (state)->H.narrow[23] = h50; \ - (state)->H.narrow[24] = h63; \ - (state)->H.narrow[25] = h62; \ - (state)->H.narrow[26] = h61; \ - (state)->H.narrow[27] = h60; \ - (state)->H.narrow[28] = h73; \ - (state)->H.narrow[29] = h72; \ - (state)->H.narrow[30] = h71; \ - (state)->H.narrow[31] = h70; \ - } while (0) - -#define INPUT_BUF1 \ - sph_u32 m03 = dec32e_aligned(buf + 0); \ - sph_u32 m02 = dec32e_aligned(buf + 4); \ - sph_u32 m01 = dec32e_aligned(buf + 8); \ - sph_u32 m00 = dec32e_aligned(buf + 12); \ - sph_u32 m13 = dec32e_aligned(buf + 16); \ - sph_u32 m12 = dec32e_aligned(buf + 20); \ - sph_u32 m11 = dec32e_aligned(buf + 24); \ - sph_u32 m10 = dec32e_aligned(buf + 28); \ - sph_u32 m23 = dec32e_aligned(buf + 32); \ - sph_u32 m22 = dec32e_aligned(buf + 36); \ - sph_u32 m21 = dec32e_aligned(buf + 40); \ - sph_u32 m20 = dec32e_aligned(buf + 44); \ - sph_u32 m33 = dec32e_aligned(buf + 48); \ - sph_u32 m32 = dec32e_aligned(buf + 52); \ - sph_u32 m31 = dec32e_aligned(buf + 56); \ - sph_u32 m30 = dec32e_aligned(buf + 60); \ - h03 ^= m03; \ - h02 ^= m02; \ - h01 ^= m01; \ - h00 ^= m00; \ - h13 ^= m13; \ - h12 ^= m12; \ - h11 ^= m11; \ - h10 ^= m10; \ - h23 ^= m23; \ - h22 ^= m22; \ - h21 ^= m21; \ - h20 ^= m20; \ - h33 ^= m33; \ - h32 ^= m32; \ - h31 ^= m31; \ - h30 ^= m30; - -#define INPUT_BUF2 \ - h43 ^= m03; \ - h42 ^= m02; \ - h41 ^= m01; \ - h40 ^= m00; \ - h53 ^= m13; \ - h52 ^= m12; \ - h51 ^= m11; \ - h50 ^= m10; \ - h63 ^= m23; \ - h62 ^= m22; \ - h61 ^= m21; \ - h60 ^= m20; \ - h73 ^= m33; \ - h72 ^= m32; \ - h71 ^= m31; \ - h70 ^= m30; - -static const sph_u32 IV512[] = { - C32e(0x6fd14b96), C32e(0x3e00aa17), C32e(0x636a2e05), C32e(0x7a15d543), - C32e(0x8a225e8d), C32e(0x0c97ef0b), C32e(0xe9341259), C32e(0xf2b3c361), - C32e(0x891da0c1), C32e(0x536f801e), C32e(0x2aa9056b), C32e(0xea2b6d80), - C32e(0x588eccdb), C32e(0x2075baa6), C32e(0xa90f3a76), C32e(0xbaf83bf7), - C32e(0x0169e605), C32e(0x41e34a69), C32e(0x46b58a8e), C32e(0x2e6fe65a), - C32e(0x1047a7d0), C32e(0xc1843c24), C32e(0x3b6e71b1), C32e(0x2d5ac199), - C32e(0xcf57f6ec), C32e(0x9db1f856), C32e(0xa706887c), C32e(0x5716b156), - C32e(0xe3c2fcdf), C32e(0xe68517fb), C32e(0x545a4678), C32e(0xcc8cdd4b) -}; - -#endif - #define SL(ro) SLu(r + ro, ro) #define SLu(r, ro) do { \ @@ -665,8 +322,6 @@ static const sph_u32 IV512[] = { #if SPH_SMALL_FOOTPRINT_JH -#if SPH_JH_64 - /* * The "small footprint" 64-bit version just uses a partially unrolled * loop. @@ -687,67 +342,6 @@ static const sph_u32 IV512[] = { #else -#define E8 do { \ - unsigned r, g; \ - for (r = g = 0; r < 42; r ++) { \ - S(h0, h2, h4, h6, Ceven_, r); \ - S(h1, h3, h5, h7, Codd_, r); \ - L(h0, h2, h4, h6, h1, h3, h5, h7); \ - switch (g) { \ - case 0: \ - W0(h1); \ - W0(h3); \ - W0(h5); \ - W0(h7); \ - break; \ - case 1: \ - W1(h1); \ - W1(h3); \ - W1(h5); \ - W1(h7); \ - break; \ - case 2: \ - W2(h1); \ - W2(h3); \ - W2(h5); \ - W2(h7); \ - break; \ - case 3: \ - W3(h1); \ - W3(h3); \ - W3(h5); \ - W3(h7); \ - break; \ - case 4: \ - W4(h1); \ - W4(h3); \ - W4(h5); \ - W4(h7); \ - break; \ - case 5: \ - W5(h1); \ - W5(h3); \ - W5(h5); \ - W5(h7); \ - break; \ - case 6: \ - W6(h1); \ - W6(h3); \ - W6(h5); \ - W6(h7); \ - break; \ - } \ - if (++ g == 7) \ - g = 0; \ - } \ - } while (0) - -#endif - -#else - -#if SPH_JH_64 - /* * On a "true 64-bit" architecture, we can unroll at will. */ @@ -797,46 +391,14 @@ static const sph_u32 IV512[] = { SLu(41, 6); \ } while (0) -#else - -/* - * We are not aiming at a small footprint, but we are still using a - * 32-bit implementation. Full loop unrolling would smash the L1 - * cache on some "big" architectures (32 kB L1 cache). - */ - -#define E8 do { \ - unsigned r; \ - for (r = 0; r < 42; r += 7) { \ - SL(0); \ - SL(1); \ - SL(2); \ - SL(3); \ - SL(4); \ - SL(5); \ - SL(6); \ - } \ - } while (0) - -#endif - #endif static void jh_init(sph_jh_context *sc, const void *iv) { sc->ptr = 0; -#if SPH_JH_64 memcpy(sc->H.wide, iv, sizeof sc->H.wide); -#else - memcpy(sc->H.narrow, iv, sizeof sc->H.narrow); -#endif -#if SPH_64 sc->block_count = 0; -#else - sc->block_count_high = 0; - sc->block_count_low = 0; -#endif } static void @@ -870,13 +432,7 @@ jh_core(sph_jh_context *sc, const void *data, size_t len) INPUT_BUF1; E8; INPUT_BUF2; -#if SPH_64 sc->block_count ++; -#else - if ((sc->block_count_low = SPH_T32( - sc->block_count_low + 1)) == 0) - sc->block_count_high ++; -#endif ptr = 0; } } @@ -891,11 +447,7 @@ jh_close(sph_jh_context *sc, unsigned ub, unsigned n, unsigned z; unsigned char buf[128]; size_t numz, u; -#if SPH_64 sph_u64 l0, l1; -#else - sph_u32 l0, l1, l2, l3; -#endif z = 0x80 >> n; buf[0] = ((ub & -z) | z) & 0xFF; @@ -905,30 +457,13 @@ jh_close(sph_jh_context *sc, unsigned ub, unsigned n, numz = 111 - sc->ptr; } memset(buf + 1, 0, numz); -#if SPH_64 l0 = SPH_T64(sc->block_count << 9) + (sc->ptr << 3) + n; l1 = SPH_T64(sc->block_count >> 55); sph_enc64be(buf + numz + 1, l1); sph_enc64be(buf + numz + 9, l0); -#else - l0 = SPH_T32(sc->block_count_low << 9) + (sc->ptr << 3) + n; - l1 = SPH_T32(sc->block_count_low >> 23) - + SPH_T32(sc->block_count_high << 9); - l2 = SPH_T32(sc->block_count_high >> 23); - l3 = 0; - sph_enc32be(buf + numz + 1, l3); - sph_enc32be(buf + numz + 5, l2); - sph_enc32be(buf + numz + 9, l1); - sph_enc32be(buf + numz + 13, l0); -#endif jh_core(sc, buf, numz + 17); -#if SPH_JH_64 for (u = 0; u < 8; u ++) enc64e(buf + (u << 3), sc->H.wide[u + 8]); -#else - for (u = 0; u < 16; u ++) - enc32e(buf + (u << 2), sc->H.narrow[u + 16]); -#endif memcpy(dst, buf + ((16 - out_size_w32) << 2), out_size_w32 << 2); jh_init(sc, iv); } diff --git a/src/crypto/x11/keccak.c b/src/crypto/x11/keccak.c index 1ac404e9a470..10a136a37ffe 100644 --- a/src/crypto/x11/keccak.c +++ b/src/crypto/x11/keccak.c @@ -42,9 +42,7 @@ extern "C"{ /* * Parameters: * - * SPH_KECCAK_64 use a 64-bit type * SPH_KECCAK_UNROLL number of loops to unroll (0/undef for full unroll) - * SPH_KECCAK_INTERLEAVE use bit-interleaving (32-bit type only) * SPH_KECCAK_NOCOPY do not copy the state into local variables * * If there is no usable 64-bit type, the code automatically switches @@ -88,22 +86,6 @@ extern "C"{ #define SPH_SMALL_FOOTPRINT_KECCAK 1 #endif -/* - * By default, we select the 64-bit implementation if a 64-bit type - * is available, unless a 32-bit x86 is detected. - */ -#if !defined SPH_KECCAK_64 && SPH_64 \ - && !(defined __i386__ || SPH_I386_GCC || SPH_I386_MSVC) -#define SPH_KECCAK_64 1 -#endif - -/* - * If using a 32-bit implementation, we prefer to interleave. - */ -#if !SPH_KECCAK_64 && !defined SPH_KECCAK_INTERLEAVE -#define SPH_KECCAK_INTERLEAVE 1 -#endif - /* * Unroll 8 rounds on big systems, 2 rounds on small systems. */ @@ -131,8 +113,6 @@ extern "C"{ #pragma warning (disable: 4146) #endif -#if SPH_KECCAK_64 - static const sph_u64 RC[] = { SPH_C64(0x0000000000000001), SPH_C64(0x0000000000008082), SPH_C64(0x800000000000808A), SPH_C64(0x8000000080008000), @@ -364,596 +344,6 @@ static const sph_u64 RC[] = { #define ROL64(d, v, n) (d = SPH_ROTL64(v, n)) #define XOR64_IOTA XOR64 -#else - -static const struct { - sph_u32 high, low; -} RC[] = { -#if SPH_KECCAK_INTERLEAVE - { SPH_C32(0x00000000), SPH_C32(0x00000001) }, - { SPH_C32(0x00000089), SPH_C32(0x00000000) }, - { SPH_C32(0x8000008B), SPH_C32(0x00000000) }, - { SPH_C32(0x80008080), SPH_C32(0x00000000) }, - { SPH_C32(0x0000008B), SPH_C32(0x00000001) }, - { SPH_C32(0x00008000), SPH_C32(0x00000001) }, - { SPH_C32(0x80008088), SPH_C32(0x00000001) }, - { SPH_C32(0x80000082), SPH_C32(0x00000001) }, - { SPH_C32(0x0000000B), SPH_C32(0x00000000) }, - { SPH_C32(0x0000000A), SPH_C32(0x00000000) }, - { SPH_C32(0x00008082), SPH_C32(0x00000001) }, - { SPH_C32(0x00008003), SPH_C32(0x00000000) }, - { SPH_C32(0x0000808B), SPH_C32(0x00000001) }, - { SPH_C32(0x8000000B), SPH_C32(0x00000001) }, - { SPH_C32(0x8000008A), SPH_C32(0x00000001) }, - { SPH_C32(0x80000081), SPH_C32(0x00000001) }, - { SPH_C32(0x80000081), SPH_C32(0x00000000) }, - { SPH_C32(0x80000008), SPH_C32(0x00000000) }, - { SPH_C32(0x00000083), SPH_C32(0x00000000) }, - { SPH_C32(0x80008003), SPH_C32(0x00000000) }, - { SPH_C32(0x80008088), SPH_C32(0x00000001) }, - { SPH_C32(0x80000088), SPH_C32(0x00000000) }, - { SPH_C32(0x00008000), SPH_C32(0x00000001) }, - { SPH_C32(0x80008082), SPH_C32(0x00000000) } -#else - { SPH_C32(0x00000000), SPH_C32(0x00000001) }, - { SPH_C32(0x00000000), SPH_C32(0x00008082) }, - { SPH_C32(0x80000000), SPH_C32(0x0000808A) }, - { SPH_C32(0x80000000), SPH_C32(0x80008000) }, - { SPH_C32(0x00000000), SPH_C32(0x0000808B) }, - { SPH_C32(0x00000000), SPH_C32(0x80000001) }, - { SPH_C32(0x80000000), SPH_C32(0x80008081) }, - { SPH_C32(0x80000000), SPH_C32(0x00008009) }, - { SPH_C32(0x00000000), SPH_C32(0x0000008A) }, - { SPH_C32(0x00000000), SPH_C32(0x00000088) }, - { SPH_C32(0x00000000), SPH_C32(0x80008009) }, - { SPH_C32(0x00000000), SPH_C32(0x8000000A) }, - { SPH_C32(0x00000000), SPH_C32(0x8000808B) }, - { SPH_C32(0x80000000), SPH_C32(0x0000008B) }, - { SPH_C32(0x80000000), SPH_C32(0x00008089) }, - { SPH_C32(0x80000000), SPH_C32(0x00008003) }, - { SPH_C32(0x80000000), SPH_C32(0x00008002) }, - { SPH_C32(0x80000000), SPH_C32(0x00000080) }, - { SPH_C32(0x00000000), SPH_C32(0x0000800A) }, - { SPH_C32(0x80000000), SPH_C32(0x8000000A) }, - { SPH_C32(0x80000000), SPH_C32(0x80008081) }, - { SPH_C32(0x80000000), SPH_C32(0x00008080) }, - { SPH_C32(0x00000000), SPH_C32(0x80000001) }, - { SPH_C32(0x80000000), SPH_C32(0x80008008) } -#endif -}; - -#if SPH_KECCAK_INTERLEAVE - -#define INTERLEAVE(xl, xh) do { \ - sph_u32 l, h, t; \ - l = (xl); h = (xh); \ - t = (l ^ (l >> 1)) & SPH_C32(0x22222222); l ^= t ^ (t << 1); \ - t = (h ^ (h >> 1)) & SPH_C32(0x22222222); h ^= t ^ (t << 1); \ - t = (l ^ (l >> 2)) & SPH_C32(0x0C0C0C0C); l ^= t ^ (t << 2); \ - t = (h ^ (h >> 2)) & SPH_C32(0x0C0C0C0C); h ^= t ^ (t << 2); \ - t = (l ^ (l >> 4)) & SPH_C32(0x00F000F0); l ^= t ^ (t << 4); \ - t = (h ^ (h >> 4)) & SPH_C32(0x00F000F0); h ^= t ^ (t << 4); \ - t = (l ^ (l >> 8)) & SPH_C32(0x0000FF00); l ^= t ^ (t << 8); \ - t = (h ^ (h >> 8)) & SPH_C32(0x0000FF00); h ^= t ^ (t << 8); \ - t = (l ^ SPH_T32(h << 16)) & SPH_C32(0xFFFF0000); \ - l ^= t; h ^= t >> 16; \ - (xl) = l; (xh) = h; \ - } while (0) - -#define UNINTERLEAVE(xl, xh) do { \ - sph_u32 l, h, t; \ - l = (xl); h = (xh); \ - t = (l ^ SPH_T32(h << 16)) & SPH_C32(0xFFFF0000); \ - l ^= t; h ^= t >> 16; \ - t = (l ^ (l >> 8)) & SPH_C32(0x0000FF00); l ^= t ^ (t << 8); \ - t = (h ^ (h >> 8)) & SPH_C32(0x0000FF00); h ^= t ^ (t << 8); \ - t = (l ^ (l >> 4)) & SPH_C32(0x00F000F0); l ^= t ^ (t << 4); \ - t = (h ^ (h >> 4)) & SPH_C32(0x00F000F0); h ^= t ^ (t << 4); \ - t = (l ^ (l >> 2)) & SPH_C32(0x0C0C0C0C); l ^= t ^ (t << 2); \ - t = (h ^ (h >> 2)) & SPH_C32(0x0C0C0C0C); h ^= t ^ (t << 2); \ - t = (l ^ (l >> 1)) & SPH_C32(0x22222222); l ^= t ^ (t << 1); \ - t = (h ^ (h >> 1)) & SPH_C32(0x22222222); h ^= t ^ (t << 1); \ - (xl) = l; (xh) = h; \ - } while (0) - -#else - -#define INTERLEAVE(l, h) -#define UNINTERLEAVE(l, h) - -#endif - -#if SPH_KECCAK_NOCOPY - -#define a00l (kc->u.narrow[2 * 0 + 0]) -#define a00h (kc->u.narrow[2 * 0 + 1]) -#define a10l (kc->u.narrow[2 * 1 + 0]) -#define a10h (kc->u.narrow[2 * 1 + 1]) -#define a20l (kc->u.narrow[2 * 2 + 0]) -#define a20h (kc->u.narrow[2 * 2 + 1]) -#define a30l (kc->u.narrow[2 * 3 + 0]) -#define a30h (kc->u.narrow[2 * 3 + 1]) -#define a40l (kc->u.narrow[2 * 4 + 0]) -#define a40h (kc->u.narrow[2 * 4 + 1]) -#define a01l (kc->u.narrow[2 * 5 + 0]) -#define a01h (kc->u.narrow[2 * 5 + 1]) -#define a11l (kc->u.narrow[2 * 6 + 0]) -#define a11h (kc->u.narrow[2 * 6 + 1]) -#define a21l (kc->u.narrow[2 * 7 + 0]) -#define a21h (kc->u.narrow[2 * 7 + 1]) -#define a31l (kc->u.narrow[2 * 8 + 0]) -#define a31h (kc->u.narrow[2 * 8 + 1]) -#define a41l (kc->u.narrow[2 * 9 + 0]) -#define a41h (kc->u.narrow[2 * 9 + 1]) -#define a02l (kc->u.narrow[2 * 10 + 0]) -#define a02h (kc->u.narrow[2 * 10 + 1]) -#define a12l (kc->u.narrow[2 * 11 + 0]) -#define a12h (kc->u.narrow[2 * 11 + 1]) -#define a22l (kc->u.narrow[2 * 12 + 0]) -#define a22h (kc->u.narrow[2 * 12 + 1]) -#define a32l (kc->u.narrow[2 * 13 + 0]) -#define a32h (kc->u.narrow[2 * 13 + 1]) -#define a42l (kc->u.narrow[2 * 14 + 0]) -#define a42h (kc->u.narrow[2 * 14 + 1]) -#define a03l (kc->u.narrow[2 * 15 + 0]) -#define a03h (kc->u.narrow[2 * 15 + 1]) -#define a13l (kc->u.narrow[2 * 16 + 0]) -#define a13h (kc->u.narrow[2 * 16 + 1]) -#define a23l (kc->u.narrow[2 * 17 + 0]) -#define a23h (kc->u.narrow[2 * 17 + 1]) -#define a33l (kc->u.narrow[2 * 18 + 0]) -#define a33h (kc->u.narrow[2 * 18 + 1]) -#define a43l (kc->u.narrow[2 * 19 + 0]) -#define a43h (kc->u.narrow[2 * 19 + 1]) -#define a04l (kc->u.narrow[2 * 20 + 0]) -#define a04h (kc->u.narrow[2 * 20 + 1]) -#define a14l (kc->u.narrow[2 * 21 + 0]) -#define a14h (kc->u.narrow[2 * 21 + 1]) -#define a24l (kc->u.narrow[2 * 22 + 0]) -#define a24h (kc->u.narrow[2 * 22 + 1]) -#define a34l (kc->u.narrow[2 * 23 + 0]) -#define a34h (kc->u.narrow[2 * 23 + 1]) -#define a44l (kc->u.narrow[2 * 24 + 0]) -#define a44h (kc->u.narrow[2 * 24 + 1]) - -#define DECL_STATE -#define READ_STATE(state) -#define WRITE_STATE(state) - -#define INPUT_BUF(size) do { \ - size_t j; \ - for (j = 0; j < (size); j += 8) { \ - sph_u32 tl, th; \ - tl = sph_dec32le_aligned(buf + j + 0); \ - th = sph_dec32le_aligned(buf + j + 4); \ - INTERLEAVE(tl, th); \ - kc->u.narrow[(j >> 2) + 0] ^= tl; \ - kc->u.narrow[(j >> 2) + 1] ^= th; \ - } \ - } while (0) - -#define INPUT_BUF144 INPUT_BUF(144) -#define INPUT_BUF136 INPUT_BUF(136) -#define INPUT_BUF104 INPUT_BUF(104) -#define INPUT_BUF72 INPUT_BUF(72) - -#else - -#define DECL_STATE \ - sph_u32 a00l, a00h, a01l, a01h, a02l, a02h, a03l, a03h, a04l, a04h; \ - sph_u32 a10l, a10h, a11l, a11h, a12l, a12h, a13l, a13h, a14l, a14h; \ - sph_u32 a20l, a20h, a21l, a21h, a22l, a22h, a23l, a23h, a24l, a24h; \ - sph_u32 a30l, a30h, a31l, a31h, a32l, a32h, a33l, a33h, a34l, a34h; \ - sph_u32 a40l, a40h, a41l, a41h, a42l, a42h, a43l, a43h, a44l, a44h; - -#define READ_STATE(state) do { \ - a00l = (state)->u.narrow[2 * 0 + 0]; \ - a00h = (state)->u.narrow[2 * 0 + 1]; \ - a10l = (state)->u.narrow[2 * 1 + 0]; \ - a10h = (state)->u.narrow[2 * 1 + 1]; \ - a20l = (state)->u.narrow[2 * 2 + 0]; \ - a20h = (state)->u.narrow[2 * 2 + 1]; \ - a30l = (state)->u.narrow[2 * 3 + 0]; \ - a30h = (state)->u.narrow[2 * 3 + 1]; \ - a40l = (state)->u.narrow[2 * 4 + 0]; \ - a40h = (state)->u.narrow[2 * 4 + 1]; \ - a01l = (state)->u.narrow[2 * 5 + 0]; \ - a01h = (state)->u.narrow[2 * 5 + 1]; \ - a11l = (state)->u.narrow[2 * 6 + 0]; \ - a11h = (state)->u.narrow[2 * 6 + 1]; \ - a21l = (state)->u.narrow[2 * 7 + 0]; \ - a21h = (state)->u.narrow[2 * 7 + 1]; \ - a31l = (state)->u.narrow[2 * 8 + 0]; \ - a31h = (state)->u.narrow[2 * 8 + 1]; \ - a41l = (state)->u.narrow[2 * 9 + 0]; \ - a41h = (state)->u.narrow[2 * 9 + 1]; \ - a02l = (state)->u.narrow[2 * 10 + 0]; \ - a02h = (state)->u.narrow[2 * 10 + 1]; \ - a12l = (state)->u.narrow[2 * 11 + 0]; \ - a12h = (state)->u.narrow[2 * 11 + 1]; \ - a22l = (state)->u.narrow[2 * 12 + 0]; \ - a22h = (state)->u.narrow[2 * 12 + 1]; \ - a32l = (state)->u.narrow[2 * 13 + 0]; \ - a32h = (state)->u.narrow[2 * 13 + 1]; \ - a42l = (state)->u.narrow[2 * 14 + 0]; \ - a42h = (state)->u.narrow[2 * 14 + 1]; \ - a03l = (state)->u.narrow[2 * 15 + 0]; \ - a03h = (state)->u.narrow[2 * 15 + 1]; \ - a13l = (state)->u.narrow[2 * 16 + 0]; \ - a13h = (state)->u.narrow[2 * 16 + 1]; \ - a23l = (state)->u.narrow[2 * 17 + 0]; \ - a23h = (state)->u.narrow[2 * 17 + 1]; \ - a33l = (state)->u.narrow[2 * 18 + 0]; \ - a33h = (state)->u.narrow[2 * 18 + 1]; \ - a43l = (state)->u.narrow[2 * 19 + 0]; \ - a43h = (state)->u.narrow[2 * 19 + 1]; \ - a04l = (state)->u.narrow[2 * 20 + 0]; \ - a04h = (state)->u.narrow[2 * 20 + 1]; \ - a14l = (state)->u.narrow[2 * 21 + 0]; \ - a14h = (state)->u.narrow[2 * 21 + 1]; \ - a24l = (state)->u.narrow[2 * 22 + 0]; \ - a24h = (state)->u.narrow[2 * 22 + 1]; \ - a34l = (state)->u.narrow[2 * 23 + 0]; \ - a34h = (state)->u.narrow[2 * 23 + 1]; \ - a44l = (state)->u.narrow[2 * 24 + 0]; \ - a44h = (state)->u.narrow[2 * 24 + 1]; \ - } while (0) - -#define WRITE_STATE(state) do { \ - (state)->u.narrow[2 * 0 + 0] = a00l; \ - (state)->u.narrow[2 * 0 + 1] = a00h; \ - (state)->u.narrow[2 * 1 + 0] = a10l; \ - (state)->u.narrow[2 * 1 + 1] = a10h; \ - (state)->u.narrow[2 * 2 + 0] = a20l; \ - (state)->u.narrow[2 * 2 + 1] = a20h; \ - (state)->u.narrow[2 * 3 + 0] = a30l; \ - (state)->u.narrow[2 * 3 + 1] = a30h; \ - (state)->u.narrow[2 * 4 + 0] = a40l; \ - (state)->u.narrow[2 * 4 + 1] = a40h; \ - (state)->u.narrow[2 * 5 + 0] = a01l; \ - (state)->u.narrow[2 * 5 + 1] = a01h; \ - (state)->u.narrow[2 * 6 + 0] = a11l; \ - (state)->u.narrow[2 * 6 + 1] = a11h; \ - (state)->u.narrow[2 * 7 + 0] = a21l; \ - (state)->u.narrow[2 * 7 + 1] = a21h; \ - (state)->u.narrow[2 * 8 + 0] = a31l; \ - (state)->u.narrow[2 * 8 + 1] = a31h; \ - (state)->u.narrow[2 * 9 + 0] = a41l; \ - (state)->u.narrow[2 * 9 + 1] = a41h; \ - (state)->u.narrow[2 * 10 + 0] = a02l; \ - (state)->u.narrow[2 * 10 + 1] = a02h; \ - (state)->u.narrow[2 * 11 + 0] = a12l; \ - (state)->u.narrow[2 * 11 + 1] = a12h; \ - (state)->u.narrow[2 * 12 + 0] = a22l; \ - (state)->u.narrow[2 * 12 + 1] = a22h; \ - (state)->u.narrow[2 * 13 + 0] = a32l; \ - (state)->u.narrow[2 * 13 + 1] = a32h; \ - (state)->u.narrow[2 * 14 + 0] = a42l; \ - (state)->u.narrow[2 * 14 + 1] = a42h; \ - (state)->u.narrow[2 * 15 + 0] = a03l; \ - (state)->u.narrow[2 * 15 + 1] = a03h; \ - (state)->u.narrow[2 * 16 + 0] = a13l; \ - (state)->u.narrow[2 * 16 + 1] = a13h; \ - (state)->u.narrow[2 * 17 + 0] = a23l; \ - (state)->u.narrow[2 * 17 + 1] = a23h; \ - (state)->u.narrow[2 * 18 + 0] = a33l; \ - (state)->u.narrow[2 * 18 + 1] = a33h; \ - (state)->u.narrow[2 * 19 + 0] = a43l; \ - (state)->u.narrow[2 * 19 + 1] = a43h; \ - (state)->u.narrow[2 * 20 + 0] = a04l; \ - (state)->u.narrow[2 * 20 + 1] = a04h; \ - (state)->u.narrow[2 * 21 + 0] = a14l; \ - (state)->u.narrow[2 * 21 + 1] = a14h; \ - (state)->u.narrow[2 * 22 + 0] = a24l; \ - (state)->u.narrow[2 * 22 + 1] = a24h; \ - (state)->u.narrow[2 * 23 + 0] = a34l; \ - (state)->u.narrow[2 * 23 + 1] = a34h; \ - (state)->u.narrow[2 * 24 + 0] = a44l; \ - (state)->u.narrow[2 * 24 + 1] = a44h; \ - } while (0) - -#define READ64(d, off) do { \ - sph_u32 tl, th; \ - tl = sph_dec32le_aligned(buf + (off)); \ - th = sph_dec32le_aligned(buf + (off) + 4); \ - INTERLEAVE(tl, th); \ - d ## l ^= tl; \ - d ## h ^= th; \ - } while (0) - -#define INPUT_BUF144 do { \ - READ64(a00, 0); \ - READ64(a10, 8); \ - READ64(a20, 16); \ - READ64(a30, 24); \ - READ64(a40, 32); \ - READ64(a01, 40); \ - READ64(a11, 48); \ - READ64(a21, 56); \ - READ64(a31, 64); \ - READ64(a41, 72); \ - READ64(a02, 80); \ - READ64(a12, 88); \ - READ64(a22, 96); \ - READ64(a32, 104); \ - READ64(a42, 112); \ - READ64(a03, 120); \ - READ64(a13, 128); \ - READ64(a23, 136); \ - } while (0) - -#define INPUT_BUF136 do { \ - READ64(a00, 0); \ - READ64(a10, 8); \ - READ64(a20, 16); \ - READ64(a30, 24); \ - READ64(a40, 32); \ - READ64(a01, 40); \ - READ64(a11, 48); \ - READ64(a21, 56); \ - READ64(a31, 64); \ - READ64(a41, 72); \ - READ64(a02, 80); \ - READ64(a12, 88); \ - READ64(a22, 96); \ - READ64(a32, 104); \ - READ64(a42, 112); \ - READ64(a03, 120); \ - READ64(a13, 128); \ - } while (0) - -#define INPUT_BUF104 do { \ - READ64(a00, 0); \ - READ64(a10, 8); \ - READ64(a20, 16); \ - READ64(a30, 24); \ - READ64(a40, 32); \ - READ64(a01, 40); \ - READ64(a11, 48); \ - READ64(a21, 56); \ - READ64(a31, 64); \ - READ64(a41, 72); \ - READ64(a02, 80); \ - READ64(a12, 88); \ - READ64(a22, 96); \ - } while (0) - -#define INPUT_BUF72 do { \ - READ64(a00, 0); \ - READ64(a10, 8); \ - READ64(a20, 16); \ - READ64(a30, 24); \ - READ64(a40, 32); \ - READ64(a01, 40); \ - READ64(a11, 48); \ - READ64(a21, 56); \ - READ64(a31, 64); \ - } while (0) - -#define INPUT_BUF(lim) do { \ - READ64(a00, 0); \ - READ64(a10, 8); \ - READ64(a20, 16); \ - READ64(a30, 24); \ - READ64(a40, 32); \ - READ64(a01, 40); \ - READ64(a11, 48); \ - READ64(a21, 56); \ - READ64(a31, 64); \ - if ((lim) == 72) \ - break; \ - READ64(a41, 72); \ - READ64(a02, 80); \ - READ64(a12, 88); \ - READ64(a22, 96); \ - if ((lim) == 104) \ - break; \ - READ64(a32, 104); \ - READ64(a42, 112); \ - READ64(a03, 120); \ - READ64(a13, 128); \ - if ((lim) == 136) \ - break; \ - READ64(a23, 136); \ - } while (0) - -#endif - -#define DECL64(x) sph_u64 x ## l, x ## h -#define MOV64(d, s) (d ## l = s ## l, d ## h = s ## h) -#define XOR64(d, a, b) (d ## l = a ## l ^ b ## l, d ## h = a ## h ^ b ## h) -#define AND64(d, a, b) (d ## l = a ## l & b ## l, d ## h = a ## h & b ## h) -#define OR64(d, a, b) (d ## l = a ## l | b ## l, d ## h = a ## h | b ## h) -#define NOT64(d, s) (d ## l = SPH_T32(~s ## l), d ## h = SPH_T32(~s ## h)) -#define ROL64(d, v, n) ROL64_ ## n(d, v) - -#if SPH_KECCAK_INTERLEAVE - -#define ROL64_odd1(d, v) do { \ - sph_u32 tmp; \ - tmp = v ## l; \ - d ## l = SPH_T32(v ## h << 1) | (v ## h >> 31); \ - d ## h = tmp; \ - } while (0) - -#define ROL64_odd63(d, v) do { \ - sph_u32 tmp; \ - tmp = SPH_T32(v ## l << 31) | (v ## l >> 1); \ - d ## l = v ## h; \ - d ## h = tmp; \ - } while (0) - -#define ROL64_odd(d, v, n) do { \ - sph_u32 tmp; \ - tmp = SPH_T32(v ## l << (n - 1)) | (v ## l >> (33 - n)); \ - d ## l = SPH_T32(v ## h << n) | (v ## h >> (32 - n)); \ - d ## h = tmp; \ - } while (0) - -#define ROL64_even(d, v, n) do { \ - d ## l = SPH_T32(v ## l << n) | (v ## l >> (32 - n)); \ - d ## h = SPH_T32(v ## h << n) | (v ## h >> (32 - n)); \ - } while (0) - -#define ROL64_0(d, v) -#define ROL64_1(d, v) ROL64_odd1(d, v) -#define ROL64_2(d, v) ROL64_even(d, v, 1) -#define ROL64_3(d, v) ROL64_odd( d, v, 2) -#define ROL64_4(d, v) ROL64_even(d, v, 2) -#define ROL64_5(d, v) ROL64_odd( d, v, 3) -#define ROL64_6(d, v) ROL64_even(d, v, 3) -#define ROL64_7(d, v) ROL64_odd( d, v, 4) -#define ROL64_8(d, v) ROL64_even(d, v, 4) -#define ROL64_9(d, v) ROL64_odd( d, v, 5) -#define ROL64_10(d, v) ROL64_even(d, v, 5) -#define ROL64_11(d, v) ROL64_odd( d, v, 6) -#define ROL64_12(d, v) ROL64_even(d, v, 6) -#define ROL64_13(d, v) ROL64_odd( d, v, 7) -#define ROL64_14(d, v) ROL64_even(d, v, 7) -#define ROL64_15(d, v) ROL64_odd( d, v, 8) -#define ROL64_16(d, v) ROL64_even(d, v, 8) -#define ROL64_17(d, v) ROL64_odd( d, v, 9) -#define ROL64_18(d, v) ROL64_even(d, v, 9) -#define ROL64_19(d, v) ROL64_odd( d, v, 10) -#define ROL64_20(d, v) ROL64_even(d, v, 10) -#define ROL64_21(d, v) ROL64_odd( d, v, 11) -#define ROL64_22(d, v) ROL64_even(d, v, 11) -#define ROL64_23(d, v) ROL64_odd( d, v, 12) -#define ROL64_24(d, v) ROL64_even(d, v, 12) -#define ROL64_25(d, v) ROL64_odd( d, v, 13) -#define ROL64_26(d, v) ROL64_even(d, v, 13) -#define ROL64_27(d, v) ROL64_odd( d, v, 14) -#define ROL64_28(d, v) ROL64_even(d, v, 14) -#define ROL64_29(d, v) ROL64_odd( d, v, 15) -#define ROL64_30(d, v) ROL64_even(d, v, 15) -#define ROL64_31(d, v) ROL64_odd( d, v, 16) -#define ROL64_32(d, v) ROL64_even(d, v, 16) -#define ROL64_33(d, v) ROL64_odd( d, v, 17) -#define ROL64_34(d, v) ROL64_even(d, v, 17) -#define ROL64_35(d, v) ROL64_odd( d, v, 18) -#define ROL64_36(d, v) ROL64_even(d, v, 18) -#define ROL64_37(d, v) ROL64_odd( d, v, 19) -#define ROL64_38(d, v) ROL64_even(d, v, 19) -#define ROL64_39(d, v) ROL64_odd( d, v, 20) -#define ROL64_40(d, v) ROL64_even(d, v, 20) -#define ROL64_41(d, v) ROL64_odd( d, v, 21) -#define ROL64_42(d, v) ROL64_even(d, v, 21) -#define ROL64_43(d, v) ROL64_odd( d, v, 22) -#define ROL64_44(d, v) ROL64_even(d, v, 22) -#define ROL64_45(d, v) ROL64_odd( d, v, 23) -#define ROL64_46(d, v) ROL64_even(d, v, 23) -#define ROL64_47(d, v) ROL64_odd( d, v, 24) -#define ROL64_48(d, v) ROL64_even(d, v, 24) -#define ROL64_49(d, v) ROL64_odd( d, v, 25) -#define ROL64_50(d, v) ROL64_even(d, v, 25) -#define ROL64_51(d, v) ROL64_odd( d, v, 26) -#define ROL64_52(d, v) ROL64_even(d, v, 26) -#define ROL64_53(d, v) ROL64_odd( d, v, 27) -#define ROL64_54(d, v) ROL64_even(d, v, 27) -#define ROL64_55(d, v) ROL64_odd( d, v, 28) -#define ROL64_56(d, v) ROL64_even(d, v, 28) -#define ROL64_57(d, v) ROL64_odd( d, v, 29) -#define ROL64_58(d, v) ROL64_even(d, v, 29) -#define ROL64_59(d, v) ROL64_odd( d, v, 30) -#define ROL64_60(d, v) ROL64_even(d, v, 30) -#define ROL64_61(d, v) ROL64_odd( d, v, 31) -#define ROL64_62(d, v) ROL64_even(d, v, 31) -#define ROL64_63(d, v) ROL64_odd63(d, v) - -#else - -#define ROL64_small(d, v, n) do { \ - sph_u32 tmp; \ - tmp = SPH_T32(v ## l << n) | (v ## h >> (32 - n)); \ - d ## h = SPH_T32(v ## h << n) | (v ## l >> (32 - n)); \ - d ## l = tmp; \ - } while (0) - -#define ROL64_0(d, v) 0 -#define ROL64_1(d, v) ROL64_small(d, v, 1) -#define ROL64_2(d, v) ROL64_small(d, v, 2) -#define ROL64_3(d, v) ROL64_small(d, v, 3) -#define ROL64_4(d, v) ROL64_small(d, v, 4) -#define ROL64_5(d, v) ROL64_small(d, v, 5) -#define ROL64_6(d, v) ROL64_small(d, v, 6) -#define ROL64_7(d, v) ROL64_small(d, v, 7) -#define ROL64_8(d, v) ROL64_small(d, v, 8) -#define ROL64_9(d, v) ROL64_small(d, v, 9) -#define ROL64_10(d, v) ROL64_small(d, v, 10) -#define ROL64_11(d, v) ROL64_small(d, v, 11) -#define ROL64_12(d, v) ROL64_small(d, v, 12) -#define ROL64_13(d, v) ROL64_small(d, v, 13) -#define ROL64_14(d, v) ROL64_small(d, v, 14) -#define ROL64_15(d, v) ROL64_small(d, v, 15) -#define ROL64_16(d, v) ROL64_small(d, v, 16) -#define ROL64_17(d, v) ROL64_small(d, v, 17) -#define ROL64_18(d, v) ROL64_small(d, v, 18) -#define ROL64_19(d, v) ROL64_small(d, v, 19) -#define ROL64_20(d, v) ROL64_small(d, v, 20) -#define ROL64_21(d, v) ROL64_small(d, v, 21) -#define ROL64_22(d, v) ROL64_small(d, v, 22) -#define ROL64_23(d, v) ROL64_small(d, v, 23) -#define ROL64_24(d, v) ROL64_small(d, v, 24) -#define ROL64_25(d, v) ROL64_small(d, v, 25) -#define ROL64_26(d, v) ROL64_small(d, v, 26) -#define ROL64_27(d, v) ROL64_small(d, v, 27) -#define ROL64_28(d, v) ROL64_small(d, v, 28) -#define ROL64_29(d, v) ROL64_small(d, v, 29) -#define ROL64_30(d, v) ROL64_small(d, v, 30) -#define ROL64_31(d, v) ROL64_small(d, v, 31) - -#define ROL64_32(d, v) do { \ - sph_u32 tmp; \ - tmp = v ## l; \ - d ## l = v ## h; \ - d ## h = tmp; \ - } while (0) - -#define ROL64_big(d, v, n) do { \ - sph_u32 trl, trh; \ - ROL64_small(tr, v, n); \ - d ## h = trl; \ - d ## l = trh; \ - } while (0) - -#define ROL64_33(d, v) ROL64_big(d, v, 1) -#define ROL64_34(d, v) ROL64_big(d, v, 2) -#define ROL64_35(d, v) ROL64_big(d, v, 3) -#define ROL64_36(d, v) ROL64_big(d, v, 4) -#define ROL64_37(d, v) ROL64_big(d, v, 5) -#define ROL64_38(d, v) ROL64_big(d, v, 6) -#define ROL64_39(d, v) ROL64_big(d, v, 7) -#define ROL64_40(d, v) ROL64_big(d, v, 8) -#define ROL64_41(d, v) ROL64_big(d, v, 9) -#define ROL64_42(d, v) ROL64_big(d, v, 10) -#define ROL64_43(d, v) ROL64_big(d, v, 11) -#define ROL64_44(d, v) ROL64_big(d, v, 12) -#define ROL64_45(d, v) ROL64_big(d, v, 13) -#define ROL64_46(d, v) ROL64_big(d, v, 14) -#define ROL64_47(d, v) ROL64_big(d, v, 15) -#define ROL64_48(d, v) ROL64_big(d, v, 16) -#define ROL64_49(d, v) ROL64_big(d, v, 17) -#define ROL64_50(d, v) ROL64_big(d, v, 18) -#define ROL64_51(d, v) ROL64_big(d, v, 19) -#define ROL64_52(d, v) ROL64_big(d, v, 20) -#define ROL64_53(d, v) ROL64_big(d, v, 21) -#define ROL64_54(d, v) ROL64_big(d, v, 22) -#define ROL64_55(d, v) ROL64_big(d, v, 23) -#define ROL64_56(d, v) ROL64_big(d, v, 24) -#define ROL64_57(d, v) ROL64_big(d, v, 25) -#define ROL64_58(d, v) ROL64_big(d, v, 26) -#define ROL64_59(d, v) ROL64_big(d, v, 27) -#define ROL64_60(d, v) ROL64_big(d, v, 28) -#define ROL64_61(d, v) ROL64_big(d, v, 29) -#define ROL64_62(d, v) ROL64_big(d, v, 30) -#define ROL64_63(d, v) ROL64_big(d, v, 31) - -#endif - -#define XOR64_IOTA(d, s, k) \ - (d ## l = s ## l ^ k.low, d ## h = s ## h ^ k.high) - -#endif #define TH_ELT(t, c0, c1, c2, c3, c4, d0, d1, d2, d3, d4) do { \ DECL64(tt0); \ @@ -1527,7 +917,6 @@ keccak_init(sph_keccak_context *kc, unsigned out_size) { int i; -#if SPH_KECCAK_64 for (i = 0; i < 25; i ++) kc->u.wide[i] = 0; /* @@ -1539,28 +928,7 @@ keccak_init(sph_keccak_context *kc, unsigned out_size) kc->u.wide[12] = SPH_C64(0xFFFFFFFFFFFFFFFF); kc->u.wide[17] = SPH_C64(0xFFFFFFFFFFFFFFFF); kc->u.wide[20] = SPH_C64(0xFFFFFFFFFFFFFFFF); -#else - for (i = 0; i < 50; i ++) - kc->u.narrow[i] = 0; - /* - * Initialization for the "lane complement". - * Note: since we set to all-one full 64-bit words, - * interleaving (if applicable) is a no-op. - */ - kc->u.narrow[ 2] = SPH_C32(0xFFFFFFFF); - kc->u.narrow[ 3] = SPH_C32(0xFFFFFFFF); - kc->u.narrow[ 4] = SPH_C32(0xFFFFFFFF); - kc->u.narrow[ 5] = SPH_C32(0xFFFFFFFF); - kc->u.narrow[16] = SPH_C32(0xFFFFFFFF); - kc->u.narrow[17] = SPH_C32(0xFFFFFFFF); - kc->u.narrow[24] = SPH_C32(0xFFFFFFFF); - kc->u.narrow[25] = SPH_C32(0xFFFFFFFF); - kc->u.narrow[34] = SPH_C32(0xFFFFFFFF); - kc->u.narrow[35] = SPH_C32(0xFFFFFFFF); - kc->u.narrow[40] = SPH_C32(0xFFFFFFFF); - kc->u.narrow[41] = SPH_C32(0xFFFFFFFF); -#endif kc->ptr = 0; kc->lim = 200 - (out_size >> 2); } @@ -1602,8 +970,6 @@ keccak_core(sph_keccak_context *kc, const void *data, size_t len, size_t lim) kc->ptr = ptr; } -#if SPH_KECCAK_64 - #define DEFCLOSE(d, lim) \ static void keccak_close ## d( \ sph_keccak_context *kc, unsigned ub, unsigned n, void *dst) \ @@ -1646,60 +1012,6 @@ keccak_core(sph_keccak_context *kc, const void *data, size_t len, size_t lim) keccak_init(kc, (unsigned)d << 3); \ } \ -#else - -#define DEFCLOSE(d, lim) \ - static void keccak_close ## d( \ - sph_keccak_context *kc, unsigned ub, unsigned n, void *dst) \ - { \ - unsigned eb; \ - union { \ - unsigned char tmp[lim + 1]; \ - sph_u64 dummy; /* for alignment */ \ - } u; \ - size_t j; \ - \ - eb = (0x100 | (ub & 0xFF)) >> (8 - n); \ - if (kc->ptr == (lim - 1)) { \ - if (n == 7) { \ - u.tmp[0] = eb; \ - memset(u.tmp + 1, 0, lim - 1); \ - u.tmp[lim] = 0x80; \ - j = 1 + lim; \ - } else { \ - u.tmp[0] = eb | 0x80; \ - j = 1; \ - } \ - } else { \ - j = lim - kc->ptr; \ - u.tmp[0] = eb; \ - memset(u.tmp + 1, 0, j - 2); \ - u.tmp[j - 1] = 0x80; \ - } \ - keccak_core(kc, u.tmp, j, lim); \ - /* Finalize the "lane complement" */ \ - kc->u.narrow[ 2] = ~kc->u.narrow[ 2]; \ - kc->u.narrow[ 3] = ~kc->u.narrow[ 3]; \ - kc->u.narrow[ 4] = ~kc->u.narrow[ 4]; \ - kc->u.narrow[ 5] = ~kc->u.narrow[ 5]; \ - kc->u.narrow[16] = ~kc->u.narrow[16]; \ - kc->u.narrow[17] = ~kc->u.narrow[17]; \ - kc->u.narrow[24] = ~kc->u.narrow[24]; \ - kc->u.narrow[25] = ~kc->u.narrow[25]; \ - kc->u.narrow[34] = ~kc->u.narrow[34]; \ - kc->u.narrow[35] = ~kc->u.narrow[35]; \ - kc->u.narrow[40] = ~kc->u.narrow[40]; \ - kc->u.narrow[41] = ~kc->u.narrow[41]; \ - /* un-interleave */ \ - for (j = 0; j < 50; j += 2) \ - UNINTERLEAVE(kc->u.narrow[j], kc->u.narrow[j + 1]); \ - for (j = 0; j < d; j += 4) \ - sph_enc32le_aligned(u.tmp + j, kc->u.narrow[j >> 2]); \ - memcpy(dst, u.tmp, d); \ - keccak_init(kc, (unsigned)d << 3); \ - } \ - -#endif DEFCLOSE(64, 72) diff --git a/src/crypto/x11/luffa.c b/src/crypto/x11/luffa.c index 6a04047b67e5..69d37d6d09c6 100644 --- a/src/crypto/x11/luffa.c +++ b/src/crypto/x11/luffa.c @@ -39,9 +39,7 @@ extern "C"{ #endif -#if SPH_64_TRUE && !defined SPH_LUFFA_PARALLEL #define SPH_LUFFA_PARALLEL 1 -#endif #ifdef _MSC_VER #pragma warning (disable: 4146) diff --git a/src/crypto/x11/simd.c b/src/crypto/x11/simd.c index 7bd519eac60b..1531426bf5f3 100644 --- a/src/crypto/x11/simd.c +++ b/src/crypto/x11/simd.c @@ -213,42 +213,6 @@ static const s32 alpha_tab[] = { FFT_LOOP(rb, 32, 4, id); \ } while (0) -#if SPH_SMALL_FOOTPRINT_SIMD - -static void -fft32(unsigned char *x, size_t xs, s32 *q) -{ - size_t xd; - - xd = xs << 1; - FFT16(0, xd, 0); - FFT16(xs, xd, 16); - FFT_LOOP(0, 16, 8, label_); -} - -#define FFT128(xb, xs, rb, id) do { \ - fft32(x + (xb) + ((xs) * 0), (xs) << 2, &q[(rb) + 0]); \ - fft32(x + (xb) + ((xs) * 2), (xs) << 2, &q[(rb) + 32]); \ - FFT_LOOP(rb, 32, 4, XCAT(id, aa)); \ - fft32(x + (xb) + ((xs) * 1), (xs) << 2, &q[(rb) + 64]); \ - fft32(x + (xb) + ((xs) * 3), (xs) << 2, &q[(rb) + 96]); \ - FFT_LOOP((rb) + 64, 32, 4, XCAT(id, ab)); \ - FFT_LOOP(rb, 64, 2, XCAT(id, a)); \ - } while (0) - -#else - -/* - * Output range: |q| <= 4733784 - */ -#define FFT128(xb, xs, rb, id) do { \ - FFT64(xb, (xs) << 1, rb, XCAT(id, a)); \ - FFT64((xb) + (xs), (xs) << 1, (rb) + 64, XCAT(id, b)); \ - FFT_LOOP(rb, 64, 2, id); \ - } while (0) - -#endif - /* * For SIMD-384 / SIMD-512, the fully unrolled FFT yields a compression * function which does not fit in the 32 kB L1 cache of a typical x86 diff --git a/src/crypto/x11/skein.c b/src/crypto/x11/skein.c index 32be99dba41e..ba1d21a08b50 100644 --- a/src/crypto/x11/skein.c +++ b/src/crypto/x11/skein.c @@ -48,8 +48,6 @@ extern "C"{ #pragma warning (disable: 4146) #endif -#if SPH_64 - /* * M9_ ## s ## _ ## i evaluates to s+i mod 9 (0 <= s <= 18, 0 <= i <= 7). */ @@ -705,9 +703,6 @@ sph_skein512_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst) sph_skein512_init(cc); } -#endif - - #ifdef __cplusplus } #endif diff --git a/src/crypto/x11/sph_blake.h b/src/crypto/x11/sph_blake.h index 137e6e6e7830..a4c0a4b1c392 100644 --- a/src/crypto/x11/sph_blake.h +++ b/src/crypto/x11/sph_blake.h @@ -44,17 +44,11 @@ extern "C"{ #include #include "sph_types.h" -#if SPH_64 - /** * Output size (in bits) for BLAKE-512. */ #define SPH_SIZE_blake512 512 -#endif - -#if SPH_64 - /** * This structure is a context for BLAKE-384 and BLAKE-512 computations: * it contains the intermediate values and some data from the last @@ -79,10 +73,6 @@ typedef struct { */ typedef sph_blake_big_context sph_blake512_context; -#endif - -#if SPH_64 - /** * Initialize a BLAKE-512 context. This process performs no memory allocation. * @@ -128,8 +118,6 @@ void sph_blake512_close(void *cc, void *dst); void sph_blake512_addbits_and_close( void *cc, unsigned ub, unsigned n, void *dst); -#endif - #ifdef __cplusplus } #endif diff --git a/src/crypto/x11/sph_bmw.h b/src/crypto/x11/sph_bmw.h index 39a38cd4804d..0b71492a95e7 100644 --- a/src/crypto/x11/sph_bmw.h +++ b/src/crypto/x11/sph_bmw.h @@ -43,17 +43,11 @@ extern "C"{ #include #include "sph_types.h" -#if SPH_64 - /** * Output size (in bits) for BMW-512. */ #define SPH_SIZE_bmw512 512 -#endif - -#if SPH_64 - /** * This structure is a context for BMW-384 and BMW-512 computations: * it contains the intermediate values and some data from the last @@ -77,10 +71,6 @@ typedef struct { */ typedef sph_bmw_big_context sph_bmw512_context; -#endif - -#if SPH_64 - /** * Initialize a BMW-512 context. This process performs no memory allocation. * @@ -126,8 +116,6 @@ void sph_bmw512_close(void *cc, void *dst); void sph_bmw512_addbits_and_close( void *cc, unsigned ub, unsigned n, void *dst); -#endif - #ifdef __cplusplus } #endif diff --git a/src/crypto/x11/sph_echo.h b/src/crypto/x11/sph_echo.h index 53b63a55ad8a..b8403b3c7073 100644 --- a/src/crypto/x11/sph_echo.h +++ b/src/crypto/x11/sph_echo.h @@ -64,9 +64,7 @@ typedef struct { size_t ptr; union { sph_u32 Vs[8][4]; -#if SPH_64 sph_u64 Vb[8][2]; -#endif } u; sph_u32 C0, C1, C2, C3; } sph_echo_big_context; diff --git a/src/crypto/x11/sph_groestl.h b/src/crypto/x11/sph_groestl.h index 318d315e815c..779bd9f3ff25 100644 --- a/src/crypto/x11/sph_groestl.h +++ b/src/crypto/x11/sph_groestl.h @@ -61,16 +61,10 @@ typedef struct { unsigned char buf[128]; /* first field, for alignment */ size_t ptr; union { -#if SPH_64 sph_u64 wide[16]; -#endif sph_u32 narrow[32]; } state; -#if SPH_64 sph_u64 count; -#else - sph_u32 count_high, count_low; -#endif } sph_groestl_big_context; /** diff --git a/src/crypto/x11/sph_jh.h b/src/crypto/x11/sph_jh.h index e017381fcc6b..06b72c6314d5 100644 --- a/src/crypto/x11/sph_jh.h +++ b/src/crypto/x11/sph_jh.h @@ -62,16 +62,10 @@ typedef struct { unsigned char buf[64]; /* first field, for alignment */ size_t ptr; union { -#if SPH_64 sph_u64 wide[16]; -#endif sph_u32 narrow[32]; } H; -#if SPH_64 sph_u64 block_count; -#else - sph_u32 block_count_high, block_count_low; -#endif } sph_jh_context; /** diff --git a/src/crypto/x11/sph_keccak.h b/src/crypto/x11/sph_keccak.h index 9925c4c15e12..43db8461c2a4 100644 --- a/src/crypto/x11/sph_keccak.h +++ b/src/crypto/x11/sph_keccak.h @@ -62,9 +62,7 @@ typedef struct { unsigned char buf[144]; /* first field, for alignment */ size_t ptr, lim; union { -#if SPH_64 sph_u64 wide[25]; -#endif sph_u32 narrow[50]; } u; } sph_keccak_context; diff --git a/src/crypto/x11/sph_skein.h b/src/crypto/x11/sph_skein.h index e17965df03aa..fd0bc6726b2a 100644 --- a/src/crypto/x11/sph_skein.h +++ b/src/crypto/x11/sph_skein.h @@ -48,8 +48,6 @@ extern "C"{ #include #include "sph_types.h" -#if SPH_64 - /** * Output size (in bits) for Skein-512. */ @@ -122,8 +120,6 @@ void sph_skein512_close(void *cc, void *dst); void sph_skein512_addbits_and_close( void *cc, unsigned ub, unsigned n, void *dst); -#endif - #ifdef __cplusplus } #endif diff --git a/src/crypto/x11/sph_types.h b/src/crypto/x11/sph_types.h index fd935225c34c..cb0066b6c1ba 100644 --- a/src/crypto/x11/sph_types.h +++ b/src/crypto/x11/sph_types.h @@ -57,18 +57,6 @@ #error This code requires 8-bit bytes #endif -/* - * We want to define the types "sph_u32" and "sph_u64" which hold - * unsigned values of at least, respectively, 32 and 64 bits. These - * tests should select appropriate types for most platforms. The - * macro "SPH_64" is defined if the 64-bit is supported. - */ - -#undef SPH_64 -#undef SPH_64_TRUE - -#if defined __STDC__ && __STDC_VERSION__ >= 199901L - /* * On C99 implementations, we can use to get an exact 64-bit * type, if any, or otherwise use a wider type (which must exist, for @@ -84,7 +72,6 @@ typedef int32_t sph_s32; typedef uint_fast32_t sph_u32; typedef int_fast32_t sph_s32; #endif -#if !SPH_NO_64 #ifdef UINT64_MAX typedef uint64_t sph_u64; typedef int64_t sph_s64; @@ -92,87 +79,9 @@ typedef int64_t sph_s64; typedef uint_fast64_t sph_u64; typedef int_fast64_t sph_s64; #endif -#endif #define SPH_C32(x) ((sph_u32)(x)) -#if !SPH_NO_64 #define SPH_C64(x) ((sph_u64)(x)) -#define SPH_64 1 -#endif - -#else - -/* - * On non-C99 systems, we use "unsigned int" if it is wide enough, - * "unsigned long" otherwise. This supports all "reasonable" architectures. - * We have to be cautious: pre-C99 preprocessors handle constants - * differently in '#if' expressions. Hence the shifts to test UINT_MAX. - */ - -#if ((UINT_MAX >> 11) >> 11) >= 0x3FF - -typedef unsigned int sph_u32; -typedef int sph_s32; - -#define SPH_C32(x) ((sph_u32)(x ## U)) - -#else - -typedef unsigned long sph_u32; -typedef long sph_s32; - -#define SPH_C32(x) ((sph_u32)(x ## UL)) - -#endif - -#if !SPH_NO_64 - -/* - * We want a 64-bit type. We use "unsigned long" if it is wide enough (as - * is common on 64-bit architectures such as AMD64, Alpha or Sparcv9), - * "unsigned long long" otherwise, if available. We use ULLONG_MAX to - * test whether "unsigned long long" is available; we also know that - * gcc features this type, even if the libc header do not know it. - */ - -#if ((ULONG_MAX >> 31) >> 31) >= 3 - -typedef unsigned long sph_u64; -typedef long sph_s64; - -#define SPH_C64(x) ((sph_u64)(x ## UL)) - -#define SPH_64 1 - -#elif ((ULLONG_MAX >> 31) >> 31) >= 3 || defined __GNUC__ - -typedef unsigned long long sph_u64; -typedef long long sph_s64; - -#define SPH_C64(x) ((sph_u64)(x ## ULL)) - -#define SPH_64 1 - -#else - -/* - * No 64-bit type... - */ - -#endif - -#endif - -#endif - -/* - * If the "unsigned long" type has length 64 bits or more, then this is - * a "true" 64-bit architectures. This is also true with Visual C on - * amd64, even though the "long" type is limited to 32 bits. - */ -#if SPH_64 && (((ULONG_MAX >> 31) >> 31) >= 3 || defined _M_X64) -#define SPH_64_TRUE 1 -#endif /* * Implementation note: some processors have specific opcodes to perform @@ -184,14 +93,10 @@ typedef long long sph_s64; #define SPH_ROTL32(x, n) SPH_T32(((x) << (n)) | ((x) >> (32 - (n)))) #define SPH_ROTR32(x, n) SPH_ROTL32(x, (32 - (n))) -#if SPH_64 - #define SPH_T64(x) ((x) & SPH_C64(0xFFFFFFFFFFFFFFFF)) #define SPH_ROTL64(x, n) SPH_T64(((x) << (n)) | ((x) >> (64 - (n)))) #define SPH_ROTR64(x, n) SPH_ROTL64(x, (64 - (n))) -#endif - /* * Define SPH_INLINE to be an "inline" qualifier, if available. We define * some small macro-like functions which benefit greatly from being inlined. @@ -333,11 +238,7 @@ typedef long long sph_s64; * it again. */ #if defined __GNUC__ -#if SPH_64_TRUE #define SPH_DETECT_PPC64_GCC 1 -#else -#define SPH_DETECT_PPC32_GCC 1 -#endif #endif #if defined __BIG_ENDIAN__ || defined _BIG_ENDIAN @@ -440,8 +341,6 @@ sph_bswap32(sph_u32 x) return x; } -#if SPH_64 - static SPH_INLINE sph_u64 sph_bswap64(sph_u64 x) { @@ -449,8 +348,6 @@ sph_bswap64(sph_u64 x) | (sph_u64)sph_bswap32((sph_u32)(x >> 32)); } -#endif - #elif SPH_AMD64_GCC && !SPH_NO_ASM /* @@ -465,8 +362,6 @@ sph_bswap32(sph_u32 x) return x; } -#if SPH_64 - static SPH_INLINE sph_u64 sph_bswap64(sph_u64 x) { @@ -474,8 +369,6 @@ sph_bswap64(sph_u64 x) return x; } -#endif - #else static SPH_INLINE sph_u32 @@ -487,8 +380,6 @@ sph_bswap32(sph_u32 x) return x; } -#if SPH_64 - /** * Byte-swap a 64-bit value. * @@ -508,8 +399,6 @@ sph_bswap64(sph_u64 x) #endif -#endif - #if SPH_SPARCV9_GCC && !SPH_NO_ASM /* @@ -830,8 +719,6 @@ sph_dec32le_aligned(const void *src) #endif } -#if SPH_64 - /** * Encode a 64-bit value into the provided buffer (big endian convention). * @@ -1132,5 +1019,3 @@ sph_dec64le_aligned(const void *src) } #endif - -#endif diff --git a/src/dsnotificationinterface.cpp b/src/dsnotificationinterface.cpp index 184689904ca4..1b6d80b68737 100644 --- a/src/dsnotificationinterface.cpp +++ b/src/dsnotificationinterface.cpp @@ -12,10 +12,10 @@ #include #include +#include #include #include #include -#include #include #include #include @@ -143,7 +143,8 @@ void CDSNotificationInterface::NotifyMasternodeListChanged(bool undo, const CDet } } -void CDSNotificationInterface::NotifyChainLock(const CBlockIndex* pindex, const std::shared_ptr& clsig) +void CDSNotificationInterface::NotifyChainLock(const CBlockIndex* pindex, + const std::shared_ptr& clsig) { assert(m_cj_ctx && m_llmq_ctx); diff --git a/src/dsnotificationinterface.h b/src/dsnotificationinterface.h index 92ee04aac1d3..6ca8634e2cc1 100644 --- a/src/dsnotificationinterface.h +++ b/src/dsnotificationinterface.h @@ -46,7 +46,7 @@ class CDSNotificationInterface : public CValidationInterface void BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindex) override; void BlockDisconnected(const std::shared_ptr& pblock, const CBlockIndex* pindexDisconnected) override; void NotifyMasternodeListChanged(bool undo, const CDeterministicMNList& oldMNList, const CDeterministicMNListDiff& diff) override; - void NotifyChainLock(const CBlockIndex* pindex, const std::shared_ptr& clsig) override; + void NotifyChainLock(const CBlockIndex* pindex, const std::shared_ptr& clsig) override; private: CConnman& m_connman; diff --git a/src/dummywallet.cpp b/src/dummywallet.cpp index b37c7c364cd2..e02c4b505149 100644 --- a/src/dummywallet.cpp +++ b/src/dummywallet.cpp @@ -78,7 +78,8 @@ void DummyWalletInit::AddWalletOptions(ArgsManager& argsman) const "-flushwallet", "-privdb", "-walletrejectlongchains", - "-unsafesqlitesync" + "-walletcrosschain", + "-unsafesqlitesync", }); } diff --git a/src/evo/assetlocktx.cpp b/src/evo/assetlocktx.cpp index 61878c447018..3ab20f04e0bf 100644 --- a/src/evo/assetlocktx.cpp +++ b/src/evo/assetlocktx.cpp @@ -122,11 +122,8 @@ bool CAssetUnlockPayload::VerifySig(const llmq::CQuorumManager& qman, const uint const auto& llmq_params_opt = Params().GetLLMQ(llmqType); assert(llmq_params_opt.has_value()); - // We check two quorums before DEPLOYMENT_WITHDRAWALS activation - // and "all active quorums + 1 the latest inactive" after activation. - const int quorums_to_scan = DeploymentActiveAt(*pindexTip, Params().GetConsensus(), Consensus::DEPLOYMENT_WITHDRAWALS) - ? (llmq_params_opt->signingActiveQuorumCount + 1) - : 2; + // We check all active quorums + 1 the latest inactive + const int quorums_to_scan = llmq_params_opt->signingActiveQuorumCount + 1; const auto quorums = qman.ScanQuorums(llmqType, pindexTip, quorums_to_scan); if (bool isActive = std::any_of(quorums.begin(), quorums.end(), [&](const auto &q) { return q->qc->quorumHash == quorumHash; }); !isActive) { diff --git a/src/evo/cbtx.cpp b/src/evo/cbtx.cpp index 0ea054809917..d92bb0bee490 100644 --- a/src/evo/cbtx.cpp +++ b/src/evo/cbtx.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -43,23 +44,6 @@ bool CheckCbTx(const CCbTx& cbTx, const CBlockIndex* pindexPrev, TxValidationSta return true; } -bool CheckCbTxMerkleRoots(const CBlock& block, const CCbTx& cbTx, const CBlockIndex* pindex, - const llmq::CQuorumBlockProcessor& quorum_block_processor, BlockValidationState& state) -{ - if (pindex && cbTx.nVersion >= CCbTx::Version::MERKLE_ROOT_QUORUMS) { - uint256 calculatedMerkleRoot; - if (!CalcCbTxMerkleRootQuorums(block, pindex->pprev, quorum_block_processor, calculatedMerkleRoot, state)) { - // pass the state returned by the function above - return false; - } - if (calculatedMerkleRoot != cbTx.merkleRootQuorums) { - return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-cbtx-quorummerkleroot"); - } - } - - return true; -} - using QcHashMap = std::map>; using QcIndexedHashMap = std::map>; @@ -74,11 +58,12 @@ auto CachedGetQcHashesQcIndexedHashes(const CBlockIndex* pindexPrev, const llmq: static Mutex cs_cache; static std::map> quorums_cached GUARDED_BY(cs_cache); + static std::map, StaticSaltedHasher>> qc_hashes_cached + GUARDED_BY(cs_cache); static QcHashMap qcHashes_cached GUARDED_BY(cs_cache); static QcIndexedHashMap qcIndexedHashes_cached GUARDED_BY(cs_cache); LOCK(cs_cache); - if (quorums == quorums_cached) { return std::make_pair(qcHashes_cached, qcIndexedHashes_cached); } @@ -87,6 +72,9 @@ auto CachedGetQcHashesQcIndexedHashes(const CBlockIndex* pindexPrev, const llmq: quorums_cached.clear(); qcHashes_cached.clear(); qcIndexedHashes_cached.clear(); + if (qc_hashes_cached.empty()) { + llmq::utils::InitQuorumsCache(qc_hashes_cached); + } for (const auto& [llmqType, vecBlockIndexes] : quorums) { const auto& llmq_params_opt = Params().GetLLMQ(llmqType); @@ -96,21 +84,27 @@ auto CachedGetQcHashesQcIndexedHashes(const CBlockIndex* pindexPrev, const llmq: vec_hashes.reserve(vecBlockIndexes.size()); auto& map_indexed_hashes = qcIndexedHashes_cached[llmqType]; for (const auto& blockIndex : vecBlockIndexes) { - uint256 dummyHash; - llmq::CFinalCommitmentPtr pqc = quorum_block_processor.GetMinedCommitment(llmqType, blockIndex->GetBlockHash(), dummyHash); - if (pqc == nullptr) { - // this should never happen - return std::nullopt; + uint256 block_hash{blockIndex->GetBlockHash()}; + + std::pair qc_hash; + if (!qc_hashes_cached[llmqType].get(block_hash, qc_hash)) { + auto [pqc, dummy_hash] = quorum_block_processor.GetMinedCommitment(llmqType, block_hash); + if (dummy_hash == uint256::ZERO) { + // this should never happen + return std::nullopt; + } + qc_hash.first = ::SerializeHash(pqc); + qc_hash.second = rotation_enabled ? pqc.quorumIndex : 0; + qc_hashes_cached[llmqType].insert(block_hash, qc_hash); } - auto qcHash = ::SerializeHash(*pqc); if (rotation_enabled) { - map_indexed_hashes[pqc->quorumIndex] = qcHash; + map_indexed_hashes[qc_hash.second] = qc_hash.first; } else { - vec_hashes.emplace_back(qcHash); + vec_hashes.emplace_back(qc_hash.first); } } } - quorums_cached = quorums; + std::swap(quorums_cached, quorums); return std::make_pair(qcHashes_cached, qcIndexedHashes_cached); } diff --git a/src/evo/cbtx.h b/src/evo/cbtx.h index c9087f5866b0..482d880dd522 100644 --- a/src/evo/cbtx.h +++ b/src/evo/cbtx.h @@ -65,9 +65,6 @@ template<> struct is_serializable_enum : std::true_type {}; bool CheckCbTx(const CCbTx& cbTx, const CBlockIndex* pindexPrev, TxValidationState& state); -// This can only be done after the block has been fully processed, as otherwise we won't have the finished MN list -bool CheckCbTxMerkleRoots(const CBlock& block, const CCbTx& cbTx, const CBlockIndex* pindex, - const llmq::CQuorumBlockProcessor& quorum_block_processor, BlockValidationState& state); bool CalcCbTxMerkleRootQuorums(const CBlock& block, const CBlockIndex* pindexPrev, const llmq::CQuorumBlockProcessor& quorum_block_processor, uint256& merkleRootRet, BlockValidationState& state); diff --git a/src/evo/chainhelper.cpp b/src/evo/chainhelper.cpp index bda004ab14b3..d4661d71b724 100644 --- a/src/evo/chainhelper.cpp +++ b/src/evo/chainhelper.cpp @@ -5,10 +5,11 @@ #include #include + +#include #include #include #include -#include #include CChainstateHelper::CChainstateHelper(CCreditPoolManager& cpoolman, CDeterministicMNManager& dmnman, diff --git a/src/evo/core_write.cpp b/src/evo/core_write.cpp index e61c82d8bdc0..bab2073d0f44 100644 --- a/src/evo/core_write.cpp +++ b/src/evo/core_write.cpp @@ -197,7 +197,7 @@ ssCbTxMerkleTree << cbTxMerkleTree; obj.pushKV("cbTxMerkleTree", HexStr(ssCbTxMerkleTree)); - obj.pushKV("cbTx", EncodeHexTx(*cbTx)); + obj.pushKV("cbTx", EncodeHexTx(CTransaction(cbTx))); UniValue deletedMNsArr(UniValue::VARR); for (const auto& h : deletedMNs) { @@ -227,7 +227,7 @@ obj.pushKV("newQuorums", newQuorumsArr); // Do not assert special tx type here since this can be called prior to DIP0003 activation - if (const auto opt_cbTxPayload = GetTxPayload(*cbTx, /*assert_type=*/false)) { + if (const auto opt_cbTxPayload = GetTxPayload(cbTx, /*assert_type=*/false)) { obj.pushKV("merkleRootMNList", opt_cbTxPayload->merkleRootMNList.ToString()); if (opt_cbTxPayload->nVersion >= CCbTx::Version::MERKLE_ROOT_QUORUMS) { obj.pushKV("merkleRootQuorums", opt_cbTxPayload->merkleRootQuorums.ToString()); diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index 9202f1a4eb2d..08468ca9c5b9 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include