aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am35
-rw-r--r--src/Makefile.bench.include2
-rw-r--r--src/Makefile.qt.include2
-rw-r--r--src/Makefile.qttest.include2
-rw-r--r--src/Makefile.test.include3
-rw-r--r--src/core_write.cpp2
-rw-r--r--src/crypto/sha256.cpp74
-rw-r--r--src/crypto/sha256_arm_shani.cpp899
-rw-r--r--src/crypto/sha256_x86_shani.cpp (renamed from src/crypto/sha256_shani.cpp)6
-rw-r--r--src/qt/addressbookpage.cpp2
-rw-r--r--src/qt/bitcoin.cpp6
-rw-r--r--src/qt/bitcoingui.cpp126
-rw-r--r--src/qt/bitcoingui.h10
-rw-r--r--src/qt/guiutil.cpp2
-rw-r--r--src/qt/guiutil.h2
-rw-r--r--src/qt/sendcoinsdialog.cpp2
-rw-r--r--src/qt/transactionview.cpp4
-rw-r--r--src/qt/walletframe.cpp2
-rw-r--r--src/qt/walletview.cpp12
-rw-r--r--src/rpc/blockchain.cpp66
-rw-r--r--src/test/data/script_tests.json4
-rw-r--r--src/test/main.cpp4
-rw-r--r--src/util/syscall_sandbox.cpp1
-rw-r--r--src/versionbits.cpp2
24 files changed, 1116 insertions, 154 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 0b177480c8..417a611181 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -46,9 +46,13 @@ if ENABLE_AVX2
LIBBITCOIN_CRYPTO_AVX2 = crypto/libbitcoin_crypto_avx2.a
LIBBITCOIN_CRYPTO += $(LIBBITCOIN_CRYPTO_AVX2)
endif
-if ENABLE_SHANI
-LIBBITCOIN_CRYPTO_SHANI = crypto/libbitcoin_crypto_shani.a
-LIBBITCOIN_CRYPTO += $(LIBBITCOIN_CRYPTO_SHANI)
+if ENABLE_X86_SHANI
+LIBBITCOIN_CRYPTO_X86_SHANI = crypto/libbitcoin_crypto_x86_shani.a
+LIBBITCOIN_CRYPTO += $(LIBBITCOIN_CRYPTO_X86_SHANI)
+endif
+if ENABLE_ARM_SHANI
+LIBBITCOIN_CRYPTO_ARM_SHANI = crypto/libbitcoin_crypto_arm_shani.a
+LIBBITCOIN_CRYPTO += $(LIBBITCOIN_CRYPTO_ARM_SHANI)
endif
$(LIBSECP256K1): $(wildcard secp256k1/src/*.h) $(wildcard secp256k1/src/*.c) $(wildcard secp256k1/include/*)
@@ -498,11 +502,17 @@ crypto_libbitcoin_crypto_avx2_a_CXXFLAGS += $(AVX2_CXXFLAGS)
crypto_libbitcoin_crypto_avx2_a_CPPFLAGS += -DENABLE_AVX2
crypto_libbitcoin_crypto_avx2_a_SOURCES = crypto/sha256_avx2.cpp
-crypto_libbitcoin_crypto_shani_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-crypto_libbitcoin_crypto_shani_a_CPPFLAGS = $(AM_CPPFLAGS)
-crypto_libbitcoin_crypto_shani_a_CXXFLAGS += $(SHANI_CXXFLAGS)
-crypto_libbitcoin_crypto_shani_a_CPPFLAGS += -DENABLE_SHANI
-crypto_libbitcoin_crypto_shani_a_SOURCES = crypto/sha256_shani.cpp
+crypto_libbitcoin_crypto_x86_shani_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+crypto_libbitcoin_crypto_x86_shani_a_CPPFLAGS = $(AM_CPPFLAGS)
+crypto_libbitcoin_crypto_x86_shani_a_CXXFLAGS += $(X86_SHANI_CXXFLAGS)
+crypto_libbitcoin_crypto_x86_shani_a_CPPFLAGS += -DENABLE_X86_SHANI
+crypto_libbitcoin_crypto_x86_shani_a_SOURCES = crypto/sha256_x86_shani.cpp
+
+crypto_libbitcoin_crypto_arm_shani_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+crypto_libbitcoin_crypto_arm_shani_a_CPPFLAGS = $(AM_CPPFLAGS)
+crypto_libbitcoin_crypto_arm_shani_a_CXXFLAGS += $(ARM_SHANI_CXXFLAGS)
+crypto_libbitcoin_crypto_arm_shani_a_CPPFLAGS += -DENABLE_ARM_SHANI
+crypto_libbitcoin_crypto_arm_shani_a_SOURCES = crypto/sha256_arm_shani.cpp
# consensus: shared between all executables that validate any consensus rules.
libbitcoin_consensus_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
@@ -665,7 +675,7 @@ bitcoin_bin_ldadd = \
$(LIBMEMENV) \
$(LIBSECP256K1)
-bitcoin_bin_ldadd += $(BOOST_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(NATPMP_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS) $(SQLITE_LIBS)
+bitcoin_bin_ldadd += $(BDB_LIBS) $(MINIUPNPC_LIBS) $(NATPMP_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS) $(SQLITE_LIBS)
bitcoind_SOURCES = $(bitcoin_daemon_sources) init/bitcoind.cpp
bitcoind_CPPFLAGS = $(bitcoin_bin_cppflags)
@@ -695,7 +705,7 @@ bitcoin_cli_LDADD = \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CRYPTO)
-bitcoin_cli_LDADD += $(BOOST_LIBS) $(EVENT_LIBS)
+bitcoin_cli_LDADD += $(EVENT_LIBS)
#
# bitcoin-tx binary #
@@ -715,8 +725,6 @@ bitcoin_tx_LDADD = \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
$(LIBSECP256K1)
-
-bitcoin_tx_LDADD += $(BOOST_LIBS)
#
# bitcoin-wallet binary #
@@ -734,7 +742,6 @@ bitcoin_wallet_LDADD = \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
$(LIBSECP256K1) \
- $(BOOST_LIBS) \
$(BDB_LIBS) \
$(SQLITE_LIBS)
@@ -760,8 +767,6 @@ bitcoin_util_LDADD = \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
$(LIBSECP256K1)
-
-bitcoin_util_LDADD += $(BOOST_LIBS)
#
# bitcoinconsensus library #
diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include
index 2feb31a9e9..0bcce6ebe1 100644
--- a/src/Makefile.bench.include
+++ b/src/Makefile.bench.include
@@ -75,7 +75,7 @@ bench_bench_bitcoin_SOURCES += bench/coin_selection.cpp
bench_bench_bitcoin_SOURCES += bench/wallet_balance.cpp
endif
-bench_bench_bitcoin_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(MINIUPNPC_LIBS) $(NATPMP_LIBS) $(SQLITE_LIBS)
+bench_bench_bitcoin_LDADD += $(BDB_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(MINIUPNPC_LIBS) $(NATPMP_LIBS) $(SQLITE_LIBS)
bench_bench_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(PTHREAD_FLAGS)
CLEAN_BITCOIN_BENCH = bench/*.gcda bench/*.gcno $(GENERATED_BENCH_FILES)
diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include
index 85e3a6e16a..3491f07ee0 100644
--- a/src/Makefile.qt.include
+++ b/src/Makefile.qt.include
@@ -331,7 +331,7 @@ if ENABLE_ZMQ
bitcoin_qt_ldadd += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS)
endif
bitcoin_qt_ldadd += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) \
- $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(NATPMP_LIBS) $(LIBSECP256K1) \
+ $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(NATPMP_LIBS) $(LIBSECP256K1) \
$(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(SQLITE_LIBS)
bitcoin_qt_ldflags = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(PTHREAD_FLAGS)
bitcoin_qt_libtoolflags = $(AM_LIBTOOLFLAGS) --tag CXX
diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include
index b92d2cb6e2..8e6fa2eb0d 100644
--- a/src/Makefile.qttest.include
+++ b/src/Makefile.qttest.include
@@ -52,7 +52,7 @@ if ENABLE_ZMQ
qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS)
endif
qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) \
- $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) \
+ $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(QT_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) \
$(QR_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(NATPMP_LIBS) $(LIBSECP256K1) \
$(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(SQLITE_LIBS)
qt_test_test_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(PTHREAD_FLAGS)
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index 801745d0c6..1763dcb562 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -48,7 +48,6 @@ FUZZ_SUITE_LD_COMMON = \
$(LIBUNIVALUE) \
$(LIBLEVELDB) \
$(LIBLEVELDB_SSE42) \
- $(BOOST_LIBS) \
$(LIBMEMENV) \
$(LIBSECP256K1) \
$(MINISKETCH_LIBS) \
@@ -198,7 +197,7 @@ test_test_bitcoin_LDADD += $(LIBBITCOIN_WALLET)
endif
test_test_bitcoin_LDADD += $(LIBBITCOIN_NODE) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) \
- $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS) $(MINISKETCH_LIBS)
+ $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(LIBSECP256K1) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS) $(MINISKETCH_LIBS)
test_test_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_test_bitcoin_LDADD += $(BDB_LIBS) $(MINIUPNPC_LIBS) $(NATPMP_LIBS) $(SQLITE_LIBS)
diff --git a/src/core_write.cpp b/src/core_write.cpp
index 5ea62cf3ed..c4b6b8d27e 100644
--- a/src/core_write.cpp
+++ b/src/core_write.cpp
@@ -65,7 +65,7 @@ std::string FormatScript(const CScript& script)
ret += strprintf("0x%x ", HexStr(std::vector<uint8_t>(it2, script.end())));
break;
}
- return ret.substr(0, ret.size() - 1);
+ return ret.substr(0, ret.empty() ? ret.npos : ret.size() - 1);
}
const std::map<unsigned char, std::string> mapSigHashTypes = {
diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp
index e35d526d35..cde543e68c 100644
--- a/src/crypto/sha256.cpp
+++ b/src/crypto/sha256.cpp
@@ -10,6 +10,16 @@
#include <compat/cpuid.h>
+#if defined(__linux__) && defined(ENABLE_ARM_SHANI) && !defined(BUILD_BITCOIN_INTERNAL)
+#include <sys/auxv.h>
+#include <asm/hwcap.h>
+#endif
+
+#if defined(MAC_OSX) && defined(ENABLE_ARM_SHANI) && !defined(BUILD_BITCOIN_INTERNAL)
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#endif
+
#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
#if defined(USE_ASM)
namespace sha256_sse4
@@ -29,16 +39,26 @@ namespace sha256d64_avx2
void Transform_8way(unsigned char* out, const unsigned char* in);
}
-namespace sha256d64_shani
+namespace sha256d64_x86_shani
{
void Transform_2way(unsigned char* out, const unsigned char* in);
}
-namespace sha256_shani
+namespace sha256_x86_shani
{
void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks);
}
+namespace sha256_arm_shani
+{
+void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks);
+}
+
+namespace sha256d64_arm_shani
+{
+void Transform_2way(unsigned char* out, const unsigned char* in);
+}
+
// Internal implementation code.
namespace
{
@@ -567,7 +587,7 @@ std::string SHA256AutoDetect()
bool have_xsave = false;
bool have_avx = false;
bool have_avx2 = false;
- bool have_shani = false;
+ bool have_x86_shani = false;
bool enabled_avx = false;
(void)AVXEnabled;
@@ -575,7 +595,7 @@ std::string SHA256AutoDetect()
(void)have_avx;
(void)have_xsave;
(void)have_avx2;
- (void)have_shani;
+ (void)have_x86_shani;
(void)enabled_avx;
uint32_t eax, ebx, ecx, edx;
@@ -589,15 +609,15 @@ std::string SHA256AutoDetect()
if (have_sse4) {
GetCPUID(7, 0, eax, ebx, ecx, edx);
have_avx2 = (ebx >> 5) & 1;
- have_shani = (ebx >> 29) & 1;
+ have_x86_shani = (ebx >> 29) & 1;
}
-#if defined(ENABLE_SHANI) && !defined(BUILD_BITCOIN_INTERNAL)
- if (have_shani) {
- Transform = sha256_shani::Transform;
- TransformD64 = TransformD64Wrapper<sha256_shani::Transform>;
- TransformD64_2way = sha256d64_shani::Transform_2way;
- ret = "shani(1way,2way)";
+#if defined(ENABLE_X86_SHANI) && !defined(BUILD_BITCOIN_INTERNAL)
+ if (have_x86_shani) {
+ Transform = sha256_x86_shani::Transform;
+ TransformD64 = TransformD64Wrapper<sha256_x86_shani::Transform>;
+ TransformD64_2way = sha256d64_x86_shani::Transform_2way;
+ ret = "x86_shani(1way,2way)";
have_sse4 = false; // Disable SSE4/AVX2;
have_avx2 = false;
}
@@ -623,6 +643,38 @@ std::string SHA256AutoDetect()
#endif
#endif
+#if defined(ENABLE_ARM_SHANI) && !defined(BUILD_BITCOIN_INTERNAL)
+ bool have_arm_shani = false;
+
+#if defined(__linux__)
+#if defined(__arm__) // 32-bit
+ if (getauxval(AT_HWCAP2) & HWCAP2_SHA2) {
+ have_arm_shani = true;
+ }
+#endif
+#if defined(__aarch64__) // 64-bit
+ if (getauxval(AT_HWCAP) & HWCAP_SHA2) {
+ have_arm_shani = true;
+ }
+#endif
+#endif
+
+#if defined(MAC_OSX)
+ int val = 0;
+ size_t len = sizeof(val);
+ if (sysctlbyname("hw.optional.arm.FEAT_SHA256", &val, &len, nullptr, 0) == 0) {
+ have_arm_shani = val != 0;
+ }
+#endif
+
+ if (have_arm_shani) {
+ Transform = sha256_arm_shani::Transform;
+ TransformD64 = TransformD64Wrapper<sha256_arm_shani::Transform>;
+ TransformD64_2way = sha256d64_arm_shani::Transform_2way;
+ ret = "arm_shani(1way,2way)";
+ }
+#endif
+
assert(SelfTest());
return ret;
}
diff --git a/src/crypto/sha256_arm_shani.cpp b/src/crypto/sha256_arm_shani.cpp
new file mode 100644
index 0000000000..7ffa56be70
--- /dev/null
+++ b/src/crypto/sha256_arm_shani.cpp
@@ -0,0 +1,899 @@
+// 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.
+//
+// Based on https://github.com/noloader/SHA-Intrinsics/blob/master/sha256-arm.c,
+// Written and placed in public domain by Jeffrey Walton.
+// Based on code from ARM, and by Johannes Schneiders, Skip Hovsmith and
+// Barry O'Rourke for the mbedTLS project.
+// Variant specialized for 64-byte inputs added by Pieter Wuille.
+
+#ifdef ENABLE_ARM_SHANI
+
+#include <array>
+#include <cstdint>
+#include <cstddef>
+#include <arm_acle.h>
+#include <arm_neon.h>
+
+namespace {
+alignas(uint32x4_t) static constexpr std::array<uint32_t, 64> K =
+{
+ 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
+ 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
+ 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
+ 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
+ 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
+ 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
+ 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
+ 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
+ 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
+ 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
+ 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
+ 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
+ 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
+ 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
+ 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
+ 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,
+};
+}
+
+namespace sha256_arm_shani {
+void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks)
+{
+ uint32x4_t STATE0, STATE1, ABEF_SAVE, CDGH_SAVE;
+ uint32x4_t MSG0, MSG1, MSG2, MSG3;
+ uint32x4_t TMP0, TMP2;
+
+ // Load state
+ STATE0 = vld1q_u32(&s[0]);
+ STATE1 = vld1q_u32(&s[4]);
+
+ while (blocks--)
+ {
+ // Save state
+ ABEF_SAVE = STATE0;
+ CDGH_SAVE = STATE1;
+
+ // Load and convert input chunk to Big Endian
+ MSG0 = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(chunk + 0)));
+ MSG1 = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(chunk + 16)));
+ MSG2 = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(chunk + 32)));
+ MSG3 = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(chunk + 48)));
+ chunk += 64;
+
+ // Original implemenation preloaded message and constant addition which was 1-3% slower.
+ // Now included as first step in quad round code saving one Q Neon register
+ // "TMP0 = vaddq_u32(MSG0, vld1q_u32(&K[0]));"
+
+ // Rounds 1-4
+ TMP0 = vaddq_u32(MSG0, vld1q_u32(&K[0]));
+ TMP2 = STATE0;
+ MSG0 = vsha256su0q_u32(MSG0, MSG1);
+ STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);
+ STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);
+ MSG0 = vsha256su1q_u32(MSG0, MSG2, MSG3);
+
+ // Rounds 5-8
+ TMP0 = vaddq_u32(MSG1, vld1q_u32(&K[4]));
+ TMP2 = STATE0;
+ MSG1 = vsha256su0q_u32(MSG1, MSG2);
+ STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);
+ STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);
+ MSG1 = vsha256su1q_u32(MSG1, MSG3, MSG0);
+
+ // Rounds 9-12
+ TMP0 = vaddq_u32(MSG2, vld1q_u32(&K[8]));
+ TMP2 = STATE0;
+ MSG2 = vsha256su0q_u32(MSG2, MSG3);
+ STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);
+ STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);
+ MSG2 = vsha256su1q_u32(MSG2, MSG0, MSG1);
+
+ // Rounds 13-16
+ TMP0 = vaddq_u32(MSG3, vld1q_u32(&K[12]));
+ TMP2 = STATE0;
+ MSG3 = vsha256su0q_u32(MSG3, MSG0);
+ STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);
+ STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);
+ MSG3 = vsha256su1q_u32(MSG3, MSG1, MSG2);
+
+ // Rounds 17-20
+ TMP0 = vaddq_u32(MSG0, vld1q_u32(&K[16]));
+ TMP2 = STATE0;
+ MSG0 = vsha256su0q_u32(MSG0, MSG1);
+ STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);
+ STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);
+ MSG0 = vsha256su1q_u32(MSG0, MSG2, MSG3);
+
+ // Rounds 21-24
+ TMP0 = vaddq_u32(MSG1, vld1q_u32(&K[20]));
+ TMP2 = STATE0;
+ MSG1 = vsha256su0q_u32(MSG1, MSG2);
+ STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);
+ STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);
+ MSG1 = vsha256su1q_u32(MSG1, MSG3, MSG0);
+
+ // Rounds 25-28
+ TMP0 = vaddq_u32(MSG2, vld1q_u32(&K[24]));
+ TMP2 = STATE0;
+ MSG2 = vsha256su0q_u32(MSG2, MSG3);
+ STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);
+ STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);
+ MSG2 = vsha256su1q_u32(MSG2, MSG0, MSG1);
+
+ // Rounds 29-32
+ TMP0 = vaddq_u32(MSG3, vld1q_u32(&K[28]));
+ TMP2 = STATE0;
+ MSG3 = vsha256su0q_u32(MSG3, MSG0);
+ STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);
+ STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);
+ MSG3 = vsha256su1q_u32(MSG3, MSG1, MSG2);
+
+ // Rounds 33-36
+ TMP0 = vaddq_u32(MSG0, vld1q_u32(&K[32]));
+ TMP2 = STATE0;
+ MSG0 = vsha256su0q_u32(MSG0, MSG1);
+ STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);
+ STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);
+ MSG0 = vsha256su1q_u32(MSG0, MSG2, MSG3);
+
+ // Rounds 37-40
+ TMP0 = vaddq_u32(MSG1, vld1q_u32(&K[36]));
+ TMP2 = STATE0;
+ MSG1 = vsha256su0q_u32(MSG1, MSG2);
+ STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);
+ STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);
+ MSG1 = vsha256su1q_u32(MSG1, MSG3, MSG0);
+
+ // Rounds 41-44
+ TMP0 = vaddq_u32(MSG2, vld1q_u32(&K[40]));
+ TMP2 = STATE0;
+ MSG2 = vsha256su0q_u32(MSG2, MSG3);
+ STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);
+ STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);
+ MSG2 = vsha256su1q_u32(MSG2, MSG0, MSG1);
+
+ // Rounds 45-48
+ TMP0 = vaddq_u32(MSG3, vld1q_u32(&K[44]));
+ TMP2 = STATE0;
+ MSG3 = vsha256su0q_u32(MSG3, MSG0);
+ STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);
+ STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);
+ MSG3 = vsha256su1q_u32(MSG3, MSG1, MSG2);
+
+ // Rounds 49-52
+ TMP0 = vaddq_u32(MSG0, vld1q_u32(&K[48]));
+ TMP2 = STATE0;
+ STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);
+ STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);
+
+ // Rounds 53-56
+ TMP0 = vaddq_u32(MSG1, vld1q_u32(&K[52]));
+ TMP2 = STATE0;
+ STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);
+ STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);
+
+ // Rounds 57-60
+ TMP0 = vaddq_u32(MSG2, vld1q_u32(&K[56]));
+ TMP2 = STATE0;
+ STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);
+ STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);
+
+ // Rounds 61-64
+ TMP0 = vaddq_u32(MSG3, vld1q_u32(&K[60]));
+ TMP2 = STATE0;
+ STATE0 = vsha256hq_u32(STATE0, STATE1, TMP0);
+ STATE1 = vsha256h2q_u32(STATE1, TMP2, TMP0);
+
+ // Update state
+ STATE0 = vaddq_u32(STATE0, ABEF_SAVE);
+ STATE1 = vaddq_u32(STATE1, CDGH_SAVE);
+ }
+
+ // Save final state
+ vst1q_u32(&s[0], STATE0);
+ vst1q_u32(&s[4], STATE1);
+}
+}
+
+namespace sha256d64_arm_shani {
+void Transform_2way(unsigned char* output, const unsigned char* input)
+{
+ /* Initial state. */
+ alignas(uint32x4_t) static constexpr std::array<uint32_t, 8> INIT = {
+ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
+ 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
+ };
+
+ /* Precomputed message schedule for the 2nd transform. */
+ alignas(uint32x4_t) static constexpr std::array<uint32_t, 64> MIDS = {
+ 0xc28a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+ 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf374,
+ 0x649b69c1, 0xf0fe4786, 0x0fe1edc6, 0x240cf254,
+ 0x4fe9346f, 0x6cc984be, 0x61b9411e, 0x16f988fa,
+ 0xf2c65152, 0xa88e5a6d, 0xb019fc65, 0xb9d99ec7,
+ 0x9a1231c3, 0xe70eeaa0, 0xfdb1232b, 0xc7353eb0,
+ 0x3069bad5, 0xcb976d5f, 0x5a0f118f, 0xdc1eeefd,
+ 0x0a35b689, 0xde0b7a04, 0x58f4ca9d, 0xe15d5b16,
+ 0x007f3e86, 0x37088980, 0xa507ea32, 0x6fab9537,
+ 0x17406110, 0x0d8cd6f1, 0xcdaa3b6d, 0xc0bbbe37,
+ 0x83613bda, 0xdb48a363, 0x0b02e931, 0x6fd15ca7,
+ 0x521afaca, 0x31338431, 0x6ed41a95, 0x6d437890,
+ 0xc39c91f2, 0x9eccabbd, 0xb5c9a0e6, 0x532fb63c,
+ 0xd2c741c6, 0x07237ea3, 0xa4954b68, 0x4c191d76
+ };
+
+ /* A few precomputed message schedule values for the 3rd transform. */
+ alignas(uint32x4_t) static constexpr std::array<uint32_t, 12> FINS = {
+ 0x5807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x80000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf274
+ };
+
+ /* Padding processed in the 3rd transform (byteswapped). */
+ alignas(uint32x4_t) static constexpr std::array<uint32_t, 8> FINAL = {0x80000000, 0, 0, 0, 0, 0, 0, 0x100};
+
+ uint32x4_t STATE0A, STATE0B, STATE1A, STATE1B, ABEF_SAVEA, ABEF_SAVEB, CDGH_SAVEA, CDGH_SAVEB;
+ uint32x4_t MSG0A, MSG0B, MSG1A, MSG1B, MSG2A, MSG2B, MSG3A, MSG3B;
+ uint32x4_t TMP0A, TMP0B, TMP2A, TMP2B, TMP;
+
+ // Transform 1: Load state
+ STATE0A = vld1q_u32(&INIT[0]);
+ STATE0B = STATE0A;
+ STATE1A = vld1q_u32(&INIT[4]);
+ STATE1B = STATE1A;
+
+ // Transform 1: Load and convert input chunk to Big Endian
+ MSG0A = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(input + 0)));
+ MSG1A = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(input + 16)));
+ MSG2A = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(input + 32)));
+ MSG3A = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(input + 48)));
+ MSG0B = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(input + 64)));
+ MSG1B = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(input + 80)));
+ MSG2B = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(input + 96)));
+ MSG3B = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(input + 112)));
+
+ // Transform 1: Rounds 1-4
+ TMP = vld1q_u32(&K[0]);
+ TMP0A = vaddq_u32(MSG0A, TMP);
+ TMP0B = vaddq_u32(MSG0B, TMP);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ MSG0A = vsha256su0q_u32(MSG0A, MSG1A);
+ MSG0B = vsha256su0q_u32(MSG0B, MSG1B);
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B);
+ MSG0A = vsha256su1q_u32(MSG0A, MSG2A, MSG3A);
+ MSG0B = vsha256su1q_u32(MSG0B, MSG2B, MSG3B);
+
+ // Transform 1: Rounds 5-8
+ TMP = vld1q_u32(&K[4]);
+ TMP0A = vaddq_u32(MSG1A, TMP);
+ TMP0B = vaddq_u32(MSG1B, TMP);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ MSG1A = vsha256su0q_u32(MSG1A, MSG2A);
+ MSG1B = vsha256su0q_u32(MSG1B, MSG2B);
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B);
+ MSG1A = vsha256su1q_u32(MSG1A, MSG3A, MSG0A);
+ MSG1B = vsha256su1q_u32(MSG1B, MSG3B, MSG0B);
+
+ // Transform 1: Rounds 9-12
+ TMP = vld1q_u32(&K[8]);
+ TMP0A = vaddq_u32(MSG2A, TMP);
+ TMP0B = vaddq_u32(MSG2B, TMP);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ MSG2A = vsha256su0q_u32(MSG2A, MSG3A);
+ MSG2B = vsha256su0q_u32(MSG2B, MSG3B);
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B);
+ MSG2A = vsha256su1q_u32(MSG2A, MSG0A, MSG1A);
+ MSG2B = vsha256su1q_u32(MSG2B, MSG0B, MSG1B);
+
+ // Transform 1: Rounds 13-16
+ TMP = vld1q_u32(&K[12]);
+ TMP0A = vaddq_u32(MSG3A, TMP);
+ TMP0B = vaddq_u32(MSG3B, TMP);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ MSG3A = vsha256su0q_u32(MSG3A, MSG0A);
+ MSG3B = vsha256su0q_u32(MSG3B, MSG0B);
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B);
+ MSG3A = vsha256su1q_u32(MSG3A, MSG1A, MSG2A);
+ MSG3B = vsha256su1q_u32(MSG3B, MSG1B, MSG2B);
+
+ // Transform 1: Rounds 17-20
+ TMP = vld1q_u32(&K[16]);
+ TMP0A = vaddq_u32(MSG0A, TMP);
+ TMP0B = vaddq_u32(MSG0B, TMP);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ MSG0A = vsha256su0q_u32(MSG0A, MSG1A);
+ MSG0B = vsha256su0q_u32(MSG0B, MSG1B);
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B);
+ MSG0A = vsha256su1q_u32(MSG0A, MSG2A, MSG3A);
+ MSG0B = vsha256su1q_u32(MSG0B, MSG2B, MSG3B);
+
+ // Transform 1: Rounds 21-24
+ TMP = vld1q_u32(&K[20]);
+ TMP0A = vaddq_u32(MSG1A, TMP);
+ TMP0B = vaddq_u32(MSG1B, TMP);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ MSG1A = vsha256su0q_u32(MSG1A, MSG2A);
+ MSG1B = vsha256su0q_u32(MSG1B, MSG2B);
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B);
+ MSG1A = vsha256su1q_u32(MSG1A, MSG3A, MSG0A);
+ MSG1B = vsha256su1q_u32(MSG1B, MSG3B, MSG0B);
+
+ // Transform 1: Rounds 25-28
+ TMP = vld1q_u32(&K[24]);
+ TMP0A = vaddq_u32(MSG2A, TMP);
+ TMP0B = vaddq_u32(MSG2B, TMP);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ MSG2A = vsha256su0q_u32(MSG2A, MSG3A);
+ MSG2B = vsha256su0q_u32(MSG2B, MSG3B);
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B);
+ MSG2A = vsha256su1q_u32(MSG2A, MSG0A, MSG1A);
+ MSG2B = vsha256su1q_u32(MSG2B, MSG0B, MSG1B);
+
+ // Transform 1: Rounds 29-32
+ TMP = vld1q_u32(&K[28]);
+ TMP0A = vaddq_u32(MSG3A, TMP);
+ TMP0B = vaddq_u32(MSG3B, TMP);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ MSG3A = vsha256su0q_u32(MSG3A, MSG0A);
+ MSG3B = vsha256su0q_u32(MSG3B, MSG0B);
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B);
+ MSG3A = vsha256su1q_u32(MSG3A, MSG1A, MSG2A);
+ MSG3B = vsha256su1q_u32(MSG3B, MSG1B, MSG2B);
+
+ // Transform 1: Rounds 33-36
+ TMP = vld1q_u32(&K[32]);
+ TMP0A = vaddq_u32(MSG0A, TMP);
+ TMP0B = vaddq_u32(MSG0B, TMP);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ MSG0A = vsha256su0q_u32(MSG0A, MSG1A);
+ MSG0B = vsha256su0q_u32(MSG0B, MSG1B);
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B);
+ MSG0A = vsha256su1q_u32(MSG0A, MSG2A, MSG3A);
+ MSG0B = vsha256su1q_u32(MSG0B, MSG2B, MSG3B);
+
+ // Transform 1: Rounds 37-40
+ TMP = vld1q_u32(&K[36]);
+ TMP0A = vaddq_u32(MSG1A, TMP);
+ TMP0B = vaddq_u32(MSG1B, TMP);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ MSG1A = vsha256su0q_u32(MSG1A, MSG2A);
+ MSG1B = vsha256su0q_u32(MSG1B, MSG2B);
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B);
+ MSG1A = vsha256su1q_u32(MSG1A, MSG3A, MSG0A);
+ MSG1B = vsha256su1q_u32(MSG1B, MSG3B, MSG0B);
+
+ // Transform 1: Rounds 41-44
+ TMP = vld1q_u32(&K[40]);
+ TMP0A = vaddq_u32(MSG2A, TMP);
+ TMP0B = vaddq_u32(MSG2B, TMP);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ MSG2A = vsha256su0q_u32(MSG2A, MSG3A);
+ MSG2B = vsha256su0q_u32(MSG2B, MSG3B);
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B);
+ MSG2A = vsha256su1q_u32(MSG2A, MSG0A, MSG1A);
+ MSG2B = vsha256su1q_u32(MSG2B, MSG0B, MSG1B);
+
+ // Transform 1: Rounds 45-48
+ TMP = vld1q_u32(&K[44]);
+ TMP0A = vaddq_u32(MSG3A, TMP);
+ TMP0B = vaddq_u32(MSG3B, TMP);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ MSG3A = vsha256su0q_u32(MSG3A, MSG0A);
+ MSG3B = vsha256su0q_u32(MSG3B, MSG0B);
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B);
+ MSG3A = vsha256su1q_u32(MSG3A, MSG1A, MSG2A);
+ MSG3B = vsha256su1q_u32(MSG3B, MSG1B, MSG2B);
+
+ // Transform 1: Rounds 49-52
+ TMP = vld1q_u32(&K[48]);
+ TMP0A = vaddq_u32(MSG0A, TMP);
+ TMP0B = vaddq_u32(MSG0B, TMP);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B);
+
+ // Transform 1: Rounds 53-56
+ TMP = vld1q_u32(&K[52]);
+ TMP0A = vaddq_u32(MSG1A, TMP);
+ TMP0B = vaddq_u32(MSG1B, TMP);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B);
+
+ // Transform 1: Rounds 57-60
+ TMP = vld1q_u32(&K[56]);
+ TMP0A = vaddq_u32(MSG2A, TMP);
+ TMP0B = vaddq_u32(MSG2B, TMP);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B);
+
+ // Transform 1: Rounds 61-64
+ TMP = vld1q_u32(&K[60]);
+ TMP0A = vaddq_u32(MSG3A, TMP);
+ TMP0B = vaddq_u32(MSG3B, TMP);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B);
+
+ // Transform 1: Update state
+ TMP = vld1q_u32(&INIT[0]);
+ STATE0A = vaddq_u32(STATE0A, TMP);
+ STATE0B = vaddq_u32(STATE0B, TMP);
+ TMP = vld1q_u32(&INIT[4]);
+ STATE1A = vaddq_u32(STATE1A, TMP);
+ STATE1B = vaddq_u32(STATE1B, TMP);
+
+ // Transform 2: Save state
+ ABEF_SAVEA = STATE0A;
+ ABEF_SAVEB = STATE0B;
+ CDGH_SAVEA = STATE1A;
+ CDGH_SAVEB = STATE1B;
+
+ // Transform 2: Rounds 1-4
+ TMP = vld1q_u32(&MIDS[0]);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP);
+
+ // Transform 2: Rounds 5-8
+ TMP = vld1q_u32(&MIDS[4]);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP);
+
+ // Transform 2: Rounds 9-12
+ TMP = vld1q_u32(&MIDS[8]);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP);
+
+ // Transform 2: Rounds 13-16
+ TMP = vld1q_u32(&MIDS[12]);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP);
+
+ // Transform 2: Rounds 17-20
+ TMP = vld1q_u32(&MIDS[16]);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP);
+
+ // Transform 2: Rounds 21-24
+ TMP = vld1q_u32(&MIDS[20]);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP);
+
+ // Transform 2: Rounds 25-28
+ TMP = vld1q_u32(&MIDS[24]);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP);
+
+ // Transform 2: Rounds 29-32
+ TMP = vld1q_u32(&MIDS[28]);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP);
+
+ // Transform 2: Rounds 33-36
+ TMP = vld1q_u32(&MIDS[32]);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP);
+
+ // Transform 2: Rounds 37-40
+ TMP = vld1q_u32(&MIDS[36]);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP);
+
+ // Transform 2: Rounds 41-44
+ TMP = vld1q_u32(&MIDS[40]);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP);
+
+ // Transform 2: Rounds 45-48
+ TMP = vld1q_u32(&MIDS[44]);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP);
+
+ // Transform 2: Rounds 49-52
+ TMP = vld1q_u32(&MIDS[48]);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP);
+
+ // Transform 2: Rounds 53-56
+ TMP = vld1q_u32(&MIDS[52]);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP);
+
+ // Transform 2: Rounds 57-60
+ TMP = vld1q_u32(&MIDS[56]);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP);
+
+ // Transform 2: Rounds 61-64
+ TMP = vld1q_u32(&MIDS[60]);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP);
+
+ // Transform 2: Update state
+ STATE0A = vaddq_u32(STATE0A, ABEF_SAVEA);
+ STATE0B = vaddq_u32(STATE0B, ABEF_SAVEB);
+ STATE1A = vaddq_u32(STATE1A, CDGH_SAVEA);
+ STATE1B = vaddq_u32(STATE1B, CDGH_SAVEB);
+
+ // Transform 3: Pad previous output
+ MSG0A = STATE0A;
+ MSG0B = STATE0B;
+ MSG1A = STATE1A;
+ MSG1B = STATE1B;
+ MSG2A = vld1q_u32(&FINAL[0]);
+ MSG2B = MSG2A;
+ MSG3A = vld1q_u32(&FINAL[4]);
+ MSG3B = MSG3A;
+
+ // Transform 3: Load state
+ STATE0A = vld1q_u32(&INIT[0]);
+ STATE0B = STATE0A;
+ STATE1A = vld1q_u32(&INIT[4]);
+ STATE1B = STATE1A;
+
+ // Transform 3: Rounds 1-4
+ TMP = vld1q_u32(&K[0]);
+ TMP0A = vaddq_u32(MSG0A, TMP);
+ TMP0B = vaddq_u32(MSG0B, TMP);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ MSG0A = vsha256su0q_u32(MSG0A, MSG1A);
+ MSG0B = vsha256su0q_u32(MSG0B, MSG1B);
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B);
+ MSG0A = vsha256su1q_u32(MSG0A, MSG2A, MSG3A);
+ MSG0B = vsha256su1q_u32(MSG0B, MSG2B, MSG3B);
+
+ // Transform 3: Rounds 5-8
+ TMP = vld1q_u32(&K[4]);
+ TMP0A = vaddq_u32(MSG1A, TMP);
+ TMP0B = vaddq_u32(MSG1B, TMP);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ MSG1A = vsha256su0q_u32(MSG1A, MSG2A);
+ MSG1B = vsha256su0q_u32(MSG1B, MSG2B);
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B);
+ MSG1A = vsha256su1q_u32(MSG1A, MSG3A, MSG0A);
+ MSG1B = vsha256su1q_u32(MSG1B, MSG3B, MSG0B);
+
+ // Transform 3: Rounds 9-12
+ TMP = vld1q_u32(&FINS[0]);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ MSG2A = vld1q_u32(&FINS[4]);
+ MSG2B = MSG2A;
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP);
+ MSG2A = vsha256su1q_u32(MSG2A, MSG0A, MSG1A);
+ MSG2B = vsha256su1q_u32(MSG2B, MSG0B, MSG1B);
+
+ // Transform 3: Rounds 13-16
+ TMP = vld1q_u32(&FINS[8]);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ MSG3A = vsha256su0q_u32(MSG3A, MSG0A);
+ MSG3B = vsha256su0q_u32(MSG3B, MSG0B);
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP);
+ MSG3A = vsha256su1q_u32(MSG3A, MSG1A, MSG2A);
+ MSG3B = vsha256su1q_u32(MSG3B, MSG1B, MSG2B);
+
+ // Transform 3: Rounds 17-20
+ TMP = vld1q_u32(&K[16]);
+ TMP0A = vaddq_u32(MSG0A, TMP);
+ TMP0B = vaddq_u32(MSG0B, TMP);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ MSG0A = vsha256su0q_u32(MSG0A, MSG1A);
+ MSG0B = vsha256su0q_u32(MSG0B, MSG1B);
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B);
+ MSG0A = vsha256su1q_u32(MSG0A, MSG2A, MSG3A);
+ MSG0B = vsha256su1q_u32(MSG0B, MSG2B, MSG3B);
+
+ // Transform 3: Rounds 21-24
+ TMP = vld1q_u32(&K[20]);
+ TMP0A = vaddq_u32(MSG1A, TMP);
+ TMP0B = vaddq_u32(MSG1B, TMP);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ MSG1A = vsha256su0q_u32(MSG1A, MSG2A);
+ MSG1B = vsha256su0q_u32(MSG1B, MSG2B);
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B);
+ MSG1A = vsha256su1q_u32(MSG1A, MSG3A, MSG0A);
+ MSG1B = vsha256su1q_u32(MSG1B, MSG3B, MSG0B);
+
+ // Transform 3: Rounds 25-28
+ TMP = vld1q_u32(&K[24]);
+ TMP0A = vaddq_u32(MSG2A, TMP);
+ TMP0B = vaddq_u32(MSG2B, TMP);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ MSG2A = vsha256su0q_u32(MSG2A, MSG3A);
+ MSG2B = vsha256su0q_u32(MSG2B, MSG3B);
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B);
+ MSG2A = vsha256su1q_u32(MSG2A, MSG0A, MSG1A);
+ MSG2B = vsha256su1q_u32(MSG2B, MSG0B, MSG1B);
+
+ // Transform 3: Rounds 29-32
+ TMP = vld1q_u32(&K[28]);
+ TMP0A = vaddq_u32(MSG3A, TMP);
+ TMP0B = vaddq_u32(MSG3B, TMP);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ MSG3A = vsha256su0q_u32(MSG3A, MSG0A);
+ MSG3B = vsha256su0q_u32(MSG3B, MSG0B);
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B);
+ MSG3A = vsha256su1q_u32(MSG3A, MSG1A, MSG2A);
+ MSG3B = vsha256su1q_u32(MSG3B, MSG1B, MSG2B);
+
+ // Transform 3: Rounds 33-36
+ TMP = vld1q_u32(&K[32]);
+ TMP0A = vaddq_u32(MSG0A, TMP);
+ TMP0B = vaddq_u32(MSG0B, TMP);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ MSG0A = vsha256su0q_u32(MSG0A, MSG1A);
+ MSG0B = vsha256su0q_u32(MSG0B, MSG1B);
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B);
+ MSG0A = vsha256su1q_u32(MSG0A, MSG2A, MSG3A);
+ MSG0B = vsha256su1q_u32(MSG0B, MSG2B, MSG3B);
+
+ // Transform 3: Rounds 37-40
+ TMP = vld1q_u32(&K[36]);
+ TMP0A = vaddq_u32(MSG1A, TMP);
+ TMP0B = vaddq_u32(MSG1B, TMP);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ MSG1A = vsha256su0q_u32(MSG1A, MSG2A);
+ MSG1B = vsha256su0q_u32(MSG1B, MSG2B);
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B);
+ MSG1A = vsha256su1q_u32(MSG1A, MSG3A, MSG0A);
+ MSG1B = vsha256su1q_u32(MSG1B, MSG3B, MSG0B);
+
+ // Transform 3: Rounds 41-44
+ TMP = vld1q_u32(&K[40]);
+ TMP0A = vaddq_u32(MSG2A, TMP);
+ TMP0B = vaddq_u32(MSG2B, TMP);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ MSG2A = vsha256su0q_u32(MSG2A, MSG3A);
+ MSG2B = vsha256su0q_u32(MSG2B, MSG3B);
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B);
+ MSG2A = vsha256su1q_u32(MSG2A, MSG0A, MSG1A);
+ MSG2B = vsha256su1q_u32(MSG2B, MSG0B, MSG1B);
+
+ // Transform 3: Rounds 45-48
+ TMP = vld1q_u32(&K[44]);
+ TMP0A = vaddq_u32(MSG3A, TMP);
+ TMP0B = vaddq_u32(MSG3B, TMP);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ MSG3A = vsha256su0q_u32(MSG3A, MSG0A);
+ MSG3B = vsha256su0q_u32(MSG3B, MSG0B);
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B);
+ MSG3A = vsha256su1q_u32(MSG3A, MSG1A, MSG2A);
+ MSG3B = vsha256su1q_u32(MSG3B, MSG1B, MSG2B);
+
+ // Transform 3: Rounds 49-52
+ TMP = vld1q_u32(&K[48]);
+ TMP0A = vaddq_u32(MSG0A, TMP);
+ TMP0B = vaddq_u32(MSG0B, TMP);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B);
+
+ // Transform 3: Rounds 53-56
+ TMP = vld1q_u32(&K[52]);
+ TMP0A = vaddq_u32(MSG1A, TMP);
+ TMP0B = vaddq_u32(MSG1B, TMP);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B);
+
+ // Transform 3: Rounds 57-60
+ TMP = vld1q_u32(&K[56]);
+ TMP0A = vaddq_u32(MSG2A, TMP);
+ TMP0B = vaddq_u32(MSG2B, TMP);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B);
+
+ // Transform 3: Rounds 61-64
+ TMP = vld1q_u32(&K[60]);
+ TMP0A = vaddq_u32(MSG3A, TMP);
+ TMP0B = vaddq_u32(MSG3B, TMP);
+ TMP2A = STATE0A;
+ TMP2B = STATE0B;
+ STATE0A = vsha256hq_u32(STATE0A, STATE1A, TMP0A);
+ STATE0B = vsha256hq_u32(STATE0B, STATE1B, TMP0B);
+ STATE1A = vsha256h2q_u32(STATE1A, TMP2A, TMP0A);
+ STATE1B = vsha256h2q_u32(STATE1B, TMP2B, TMP0B);
+
+ // Transform 3: Update state
+ TMP = vld1q_u32(&INIT[0]);
+ STATE0A = vaddq_u32(STATE0A, TMP);
+ STATE0B = vaddq_u32(STATE0B, TMP);
+ TMP = vld1q_u32(&INIT[4]);
+ STATE1A = vaddq_u32(STATE1A, TMP);
+ STATE1B = vaddq_u32(STATE1B, TMP);
+
+ // Store result
+ vst1q_u8(output, vrev32q_u8(vreinterpretq_u8_u32(STATE0A)));
+ vst1q_u8(output + 16, vrev32q_u8(vreinterpretq_u8_u32(STATE1A)));
+ vst1q_u8(output + 32, vrev32q_u8(vreinterpretq_u8_u32(STATE0B)));
+ vst1q_u8(output + 48, vrev32q_u8(vreinterpretq_u8_u32(STATE1B)));
+}
+}
+
+#endif
diff --git a/src/crypto/sha256_shani.cpp b/src/crypto/sha256_x86_shani.cpp
index 4f4d5b5837..a82802199f 100644
--- a/src/crypto/sha256_shani.cpp
+++ b/src/crypto/sha256_x86_shani.cpp
@@ -6,7 +6,7 @@
// Written and placed in public domain by Jeffrey Walton.
// Based on code from Intel, and by Sean Gulley for the miTLS project.
-#ifdef ENABLE_SHANI
+#ifdef ENABLE_X86_SHANI
#include <stdint.h>
#include <immintrin.h>
@@ -74,7 +74,7 @@ void inline __attribute__((always_inline)) Save(unsigned char* out, __m128i s)
}
}
-namespace sha256_shani {
+namespace sha256_x86_shani {
void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks)
{
__m128i m0, m1, m2, m3, s0, s1, so0, so1;
@@ -139,7 +139,7 @@ void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks)
}
}
-namespace sha256d64_shani {
+namespace sha256d64_x86_shani {
void Transform_2way(unsigned char* out, const unsigned char* in)
{
diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp
index a180b03c08..d59a4345f3 100644
--- a/src/qt/addressbookpage.cpp
+++ b/src/qt/addressbookpage.cpp
@@ -189,7 +189,7 @@ void AddressBookPage::onEditAction()
dlg->setModel(model);
QModelIndex origIndex = proxyModel->mapToSource(indexes.at(0));
dlg->loadRow(origIndex.row());
- GUIUtil::ShowModalDialogAndDeleteOnClose(dlg);
+ GUIUtil::ShowModalDialogAsynchronously(dlg);
}
void AddressBookPage::on_newAddress_clicked()
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 6a2781079c..eb31287c56 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -268,7 +268,11 @@ void BitcoinApplication::createWindow(const NetworkStyle *networkStyle)
connect(window, &BitcoinGUI::quitRequested, this, &BitcoinApplication::requestShutdown);
pollShutdownTimer = new QTimer(window);
- connect(pollShutdownTimer, &QTimer::timeout, window, &BitcoinGUI::detectShutdown);
+ connect(pollShutdownTimer, &QTimer::timeout, [this]{
+ if (!QApplication::activeModalWidget()) {
+ window->detectShutdown();
+ }
+ });
}
void BitcoinApplication::createSplashScreen(const NetworkStyle *networkStyle)
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 0baacfe58c..7c22880dd1 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -261,10 +261,6 @@ void BitcoinGUI::createActions()
sendCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_2));
tabGroup->addAction(sendCoinsAction);
- sendCoinsMenuAction = new QAction(sendCoinsAction->text(), this);
- sendCoinsMenuAction->setStatusTip(sendCoinsAction->statusTip());
- sendCoinsMenuAction->setToolTip(sendCoinsMenuAction->statusTip());
-
receiveCoinsAction = new QAction(platformStyle->SingleColorIcon(":/icons/receiving_addresses"), tr("&Receive"), this);
receiveCoinsAction->setStatusTip(tr("Request payments (generates QR codes and bitcoin: URIs)"));
receiveCoinsAction->setToolTip(receiveCoinsAction->statusTip());
@@ -272,10 +268,6 @@ void BitcoinGUI::createActions()
receiveCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_3));
tabGroup->addAction(receiveCoinsAction);
- receiveCoinsMenuAction = new QAction(receiveCoinsAction->text(), this);
- receiveCoinsMenuAction->setStatusTip(receiveCoinsAction->statusTip());
- receiveCoinsMenuAction->setToolTip(receiveCoinsMenuAction->statusTip());
-
historyAction = new QAction(platformStyle->SingleColorIcon(":/icons/history"), tr("&Transactions"), this);
historyAction->setStatusTip(tr("Browse transaction history"));
historyAction->setToolTip(historyAction->statusTip());
@@ -290,12 +282,8 @@ void BitcoinGUI::createActions()
connect(overviewAction, &QAction::triggered, this, &BitcoinGUI::gotoOverviewPage);
connect(sendCoinsAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
connect(sendCoinsAction, &QAction::triggered, [this]{ gotoSendCoinsPage(); });
- connect(sendCoinsMenuAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
- connect(sendCoinsMenuAction, &QAction::triggered, [this]{ gotoSendCoinsPage(); });
connect(receiveCoinsAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
connect(receiveCoinsAction, &QAction::triggered, this, &BitcoinGUI::gotoReceiveCoinsPage);
- connect(receiveCoinsMenuAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
- connect(receiveCoinsMenuAction, &QAction::triggered, this, &BitcoinGUI::gotoReceiveCoinsPage);
connect(historyAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
connect(historyAction, &QAction::triggered, this, &BitcoinGUI::gotoHistoryPage);
#endif // ENABLE_WALLET
@@ -315,8 +303,6 @@ void BitcoinGUI::createActions()
optionsAction->setStatusTip(tr("Modify configuration options for %1").arg(PACKAGE_NAME));
optionsAction->setMenuRole(QAction::PreferencesRole);
optionsAction->setEnabled(false);
- toggleHideAction = new QAction(tr("&Show / Hide"), this);
- toggleHideAction->setStatusTip(tr("Show or hide the main Window"));
encryptWalletAction = new QAction(tr("&Encrypt Wallet…"), this);
encryptWalletAction->setStatusTip(tr("Encrypt the private keys that belong to your wallet"));
@@ -376,7 +362,6 @@ void BitcoinGUI::createActions()
connect(aboutAction, &QAction::triggered, this, &BitcoinGUI::aboutClicked);
connect(aboutQtAction, &QAction::triggered, qApp, QApplication::aboutQt);
connect(optionsAction, &QAction::triggered, this, &BitcoinGUI::optionsClicked);
- connect(toggleHideAction, &QAction::triggered, this, &BitcoinGUI::toggleHidden);
connect(showHelpMessageAction, &QAction::triggered, this, &BitcoinGUI::showHelpMessageClicked);
connect(openRPCConsoleAction, &QAction::triggered, this, &BitcoinGUI::showDebugWindow);
// prevents an open debug window from becoming stuck/unusable on client shutdown
@@ -627,8 +612,6 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel, interfaces::BlockAndH
trayIcon->setVisible(optionsModel->getShowTrayIcon());
}
} else {
- // Disable possibility to show main window via action
- toggleHideAction->setEnabled(false);
if(trayIconMenu)
{
// Disable context menu on tray icon
@@ -752,9 +735,7 @@ void BitcoinGUI::setWalletActionsEnabled(bool enabled)
{
overviewAction->setEnabled(enabled);
sendCoinsAction->setEnabled(enabled);
- sendCoinsMenuAction->setEnabled(enabled);
receiveCoinsAction->setEnabled(enabled);
- receiveCoinsMenuAction->setEnabled(enabled);
historyAction->setEnabled(enabled);
encryptWalletAction->setEnabled(enabled);
backupWalletAction->setEnabled(enabled);
@@ -784,57 +765,82 @@ void BitcoinGUI::createTrayIcon()
void BitcoinGUI::createTrayIconMenu()
{
#ifndef Q_OS_MAC
- // return if trayIcon is unset (only on non-macOSes)
- if (!trayIcon)
- return;
-
- trayIcon->setContextMenu(trayIconMenu.get());
- connect(trayIcon, &QSystemTrayIcon::activated, this, &BitcoinGUI::trayIconActivated);
-#else
- // Note: On macOS, the Dock icon is used to provide the tray's functionality.
- MacDockIconHandler *dockIconHandler = MacDockIconHandler::instance();
- connect(dockIconHandler, &MacDockIconHandler::dockIconClicked, this, &BitcoinGUI::macosDockIconActivated);
- trayIconMenu->setAsDockMenu();
-#endif
+ if (!trayIcon) return;
+#endif // Q_OS_MAC
- // Configuration of the tray icon (or Dock icon) menu
+ // Configuration of the tray icon (or Dock icon) menu.
+ QAction* show_hide_action{nullptr};
#ifndef Q_OS_MAC
// Note: On macOS, the Dock icon's menu already has Show / Hide action.
- trayIconMenu->addAction(toggleHideAction);
+ show_hide_action = trayIconMenu->addAction(QString(), this, &BitcoinGUI::toggleHidden);
trayIconMenu->addSeparator();
-#endif
+#endif // Q_OS_MAC
+
+ QAction* send_action{nullptr};
+ QAction* receive_action{nullptr};
+ QAction* sign_action{nullptr};
+ QAction* verify_action{nullptr};
if (enableWallet) {
- trayIconMenu->addAction(sendCoinsMenuAction);
- trayIconMenu->addAction(receiveCoinsMenuAction);
+ send_action = trayIconMenu->addAction(sendCoinsAction->text(), sendCoinsAction, &QAction::trigger);
+ receive_action = trayIconMenu->addAction(receiveCoinsAction->text(), receiveCoinsAction, &QAction::trigger);
trayIconMenu->addSeparator();
- trayIconMenu->addAction(signMessageAction);
- trayIconMenu->addAction(verifyMessageAction);
+ sign_action = trayIconMenu->addAction(signMessageAction->text(), signMessageAction, &QAction::trigger);
+ verify_action = trayIconMenu->addAction(verifyMessageAction->text(), verifyMessageAction, &QAction::trigger);
trayIconMenu->addSeparator();
}
- trayIconMenu->addAction(optionsAction);
- trayIconMenu->addAction(openRPCConsoleAction);
-#ifndef Q_OS_MAC // This is built-in on macOS
+ QAction* options_action = trayIconMenu->addAction(optionsAction->text(), optionsAction, &QAction::trigger);
+ options_action->setMenuRole(QAction::PreferencesRole);
+ QAction* node_window_action = trayIconMenu->addAction(openRPCConsoleAction->text(), openRPCConsoleAction, &QAction::trigger);
+ QAction* quit_action{nullptr};
+#ifndef Q_OS_MAC
+ // Note: On macOS, the Dock icon's menu already has Quit action.
trayIconMenu->addSeparator();
- trayIconMenu->addAction(quitAction);
-#endif
-}
+ quit_action = trayIconMenu->addAction(quitAction->text(), quitAction, &QAction::trigger);
-#ifndef Q_OS_MAC
-void BitcoinGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
-{
- if(reason == QSystemTrayIcon::Trigger)
- {
- // Click on system tray icon triggers show/hide of the main window
- toggleHidden();
- }
-}
+ trayIcon->setContextMenu(trayIconMenu.get());
+ connect(trayIcon, &QSystemTrayIcon::activated, [this](QSystemTrayIcon::ActivationReason reason) {
+ if (reason == QSystemTrayIcon::Trigger) {
+ // Click on system tray icon triggers show/hide of the main window
+ toggleHidden();
+ }
+ });
#else
-void BitcoinGUI::macosDockIconActivated()
-{
- show();
- activateWindow();
+ // Note: On macOS, the Dock icon is used to provide the tray's functionality.
+ MacDockIconHandler* dockIconHandler = MacDockIconHandler::instance();
+ connect(dockIconHandler, &MacDockIconHandler::dockIconClicked, [this] {
+ show();
+ activateWindow();
+ });
+ trayIconMenu->setAsDockMenu();
+#endif // Q_OS_MAC
+
+ connect(
+ // Using QSystemTrayIcon::Context is not reliable.
+ // See https://bugreports.qt.io/browse/QTBUG-91697
+ trayIconMenu.get(), &QMenu::aboutToShow,
+ [this, show_hide_action, send_action, receive_action, sign_action, verify_action, options_action, node_window_action, quit_action] {
+ if (show_hide_action) show_hide_action->setText(
+ (!isHidden() && !isMinimized() && !GUIUtil::isObscured(this)) ?
+ tr("&Hide") :
+ tr("S&how"));
+ if (QApplication::activeModalWidget()) {
+ for (QAction* a : trayIconMenu.get()->actions()) {
+ a->setEnabled(false);
+ }
+ } else {
+ if (show_hide_action) show_hide_action->setEnabled(true);
+ if (enableWallet) {
+ send_action->setEnabled(sendCoinsAction->isEnabled());
+ receive_action->setEnabled(receiveCoinsAction->isEnabled());
+ sign_action->setEnabled(signMessageAction->isEnabled());
+ verify_action->setEnabled(verifyMessageAction->isEnabled());
+ }
+ options_action->setEnabled(optionsAction->isEnabled());
+ node_window_action->setEnabled(openRPCConsoleAction->isEnabled());
+ if (quit_action) quit_action->setEnabled(true);
+ }
+ });
}
-#endif
void BitcoinGUI::optionsClicked()
{
@@ -847,7 +853,7 @@ void BitcoinGUI::aboutClicked()
return;
auto dlg = new HelpMessageDialog(this, /* about */ true);
- GUIUtil::ShowModalDialogAndDeleteOnClose(dlg);
+ GUIUtil::ShowModalDialogAsynchronously(dlg);
}
void BitcoinGUI::showDebugWindow()
@@ -992,7 +998,7 @@ void BitcoinGUI::openOptionsDialogWithTab(OptionsDialog::Tab tab)
connect(dlg, &OptionsDialog::quitOnReset, this, &BitcoinGUI::quitRequested);
dlg->setCurrentTab(tab);
dlg->setModel(clientModel->getOptionsModel());
- GUIUtil::ShowModalDialogAndDeleteOnClose(dlg);
+ GUIUtil::ShowModalDialogAsynchronously(dlg);
}
void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool header, SynchronizationState sync_state)
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index 658ab5a210..0ae5f7331e 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -137,7 +137,6 @@ private:
QAction* historyAction = nullptr;
QAction* quitAction = nullptr;
QAction* sendCoinsAction = nullptr;
- QAction* sendCoinsMenuAction = nullptr;
QAction* usedSendingAddressesAction = nullptr;
QAction* usedReceivingAddressesAction = nullptr;
QAction* signMessageAction = nullptr;
@@ -146,9 +145,7 @@ private:
QAction* m_load_psbt_clipboard_action = nullptr;
QAction* aboutAction = nullptr;
QAction* receiveCoinsAction = nullptr;
- QAction* receiveCoinsMenuAction = nullptr;
QAction* optionsAction = nullptr;
- QAction* toggleHideAction = nullptr;
QAction* encryptWalletAction = nullptr;
QAction* backupWalletAction = nullptr;
QAction* changePassphraseAction = nullptr;
@@ -302,13 +299,6 @@ public Q_SLOTS:
void showDebugWindowActivateConsole();
/** Show help message dialog */
void showHelpMessageClicked();
-#ifndef Q_OS_MAC
- /** Handle tray icon clicked */
- void trayIconActivated(QSystemTrayIcon::ActivationReason reason);
-#else
- /** Handle macOS Dock icon clicked */
- void macosDockIconActivated();
-#endif
/** Show window if hidden, unminimize when minimized, rise when obscured or show if hidden and fToggleHidden is true */
void showNormalIfMinimized() { showNormalIfMinimized(false); }
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index dc73bcd911..9565fa508f 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -984,7 +984,7 @@ void PrintSlotException(
PrintExceptionContinue(exception, description.c_str());
}
-void ShowModalDialogAndDeleteOnClose(QDialog* dialog)
+void ShowModalDialogAsynchronously(QDialog* dialog)
{
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->setWindowModality(Qt::ApplicationModal);
diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h
index 9b25b77325..0224b18b4e 100644
--- a/src/qt/guiutil.h
+++ b/src/qt/guiutil.h
@@ -426,7 +426,7 @@ namespace GUIUtil
/**
* Shows a QDialog instance asynchronously, and deletes it on close.
*/
- void ShowModalDialogAndDeleteOnClose(QDialog* dialog);
+ void ShowModalDialogAsynchronously(QDialog* dialog);
inline bool IsEscapeOrBack(int key)
{
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index e37168830e..579ef0c3fd 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -930,7 +930,7 @@ void SendCoinsDialog::coinControlButtonClicked()
{
auto dlg = new CoinControlDialog(*m_coin_control, model, platformStyle);
connect(dlg, &QDialog::finished, this, &SendCoinsDialog::coinControlUpdateLabels);
- GUIUtil::ShowModalDialogAndDeleteOnClose(dlg);
+ GUIUtil::ShowModalDialogAsynchronously(dlg);
}
// Coin Control: checkbox custom change address
diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp
index 1ab1333b72..778ef04b77 100644
--- a/src/qt/transactionview.cpp
+++ b/src/qt/transactionview.cpp
@@ -511,7 +511,7 @@ void TransactionView::editLabel()
: EditAddressDialog::EditSendingAddress, this);
dlg->setModel(addressBook);
dlg->loadRow(idx);
- GUIUtil::ShowModalDialogAndDeleteOnClose(dlg);
+ GUIUtil::ShowModalDialogAsynchronously(dlg);
}
else
{
@@ -520,7 +520,7 @@ void TransactionView::editLabel()
this);
dlg->setModel(addressBook);
dlg->setAddress(address);
- GUIUtil::ShowModalDialogAndDeleteOnClose(dlg);
+ GUIUtil::ShowModalDialogAsynchronously(dlg);
}
}
}
diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp
index 08190f0b9f..91ce420a33 100644
--- a/src/qt/walletframe.cpp
+++ b/src/qt/walletframe.cpp
@@ -226,7 +226,7 @@ void WalletFrame::gotoLoadPSBT(bool from_clipboard)
auto dlg = new PSBTOperationsDialog(this, currentWalletModel(), clientModel);
dlg->openWithPSBT(psbtx);
- GUIUtil::ShowModalDialogAndDeleteOnClose(dlg);
+ GUIUtil::ShowModalDialogAsynchronously(dlg);
}
void WalletFrame::encryptWallet()
diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp
index 7954a66995..e7ec54721a 100644
--- a/src/qt/walletview.cpp
+++ b/src/qt/walletview.cpp
@@ -208,7 +208,7 @@ void WalletView::encryptWallet()
auto dlg = new AskPassphraseDialog(AskPassphraseDialog::Encrypt, this);
dlg->setModel(walletModel);
connect(dlg, &QDialog::finished, this, &WalletView::encryptionStatusChanged);
- GUIUtil::ShowModalDialogAndDeleteOnClose(dlg);
+ GUIUtil::ShowModalDialogAsynchronously(dlg);
}
void WalletView::backupWallet()
@@ -235,16 +235,18 @@ void WalletView::changePassphrase()
{
auto dlg = new AskPassphraseDialog(AskPassphraseDialog::ChangePass, this);
dlg->setModel(walletModel);
- GUIUtil::ShowModalDialogAndDeleteOnClose(dlg);
+ GUIUtil::ShowModalDialogAsynchronously(dlg);
}
void WalletView::unlockWallet()
{
// Unlock wallet when requested by wallet model
if (walletModel->getEncryptionStatus() == WalletModel::Locked) {
- auto dlg = new AskPassphraseDialog(AskPassphraseDialog::Unlock, this);
- dlg->setModel(walletModel);
- GUIUtil::ShowModalDialogAndDeleteOnClose(dlg);
+ AskPassphraseDialog dlg(AskPassphraseDialog::Unlock, this);
+ dlg.setModel(walletModel);
+ // A modal dialog must be synchronous here as expected
+ // in the WalletModel::requestUnlock() function.
+ dlg.exec();
}
}
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 7cbe7e6159..69204e346a 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -1430,7 +1430,7 @@ static RPCHelpMan verifychain()
};
}
-static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, UniValue& softforks, const Consensus::Params& params, Consensus::BuriedDeployment dep)
+static void SoftForkDescPushBack(const CBlockIndex* blockindex, UniValue& softforks, const Consensus::Params& params, Consensus::BuriedDeployment dep)
{
// For buried deployments.
@@ -1440,17 +1440,17 @@ static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, UniValue&
rv.pushKV("type", "buried");
// getdeploymentinfo reports the softfork as active from when the chain height is
// one below the activation height
- rv.pushKV("active", DeploymentActiveAfter(active_chain_tip, params, dep));
+ rv.pushKV("active", DeploymentActiveAfter(blockindex, params, dep));
rv.pushKV("height", params.DeploymentHeight(dep));
softforks.pushKV(DeploymentName(dep), rv);
}
-static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, UniValue& softforks, const Consensus::Params& consensusParams, Consensus::DeploymentPos id)
+static void SoftForkDescPushBack(const CBlockIndex* blockindex, UniValue& softforks, const Consensus::Params& consensusParams, Consensus::DeploymentPos id)
{
// For BIP9 deployments.
if (!DeploymentEnabled(consensusParams, id)) return;
- if (active_chain_tip == nullptr) return;
+ if (blockindex == nullptr) return;
auto get_state_name = [](const ThresholdState state) -> std::string {
switch (state) {
@@ -1465,8 +1465,8 @@ static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, UniValue&
UniValue bip9(UniValue::VOBJ);
- const ThresholdState next_state = g_versionbitscache.State(active_chain_tip, consensusParams, id);
- const ThresholdState current_state = g_versionbitscache.State(active_chain_tip->pprev, consensusParams, id);
+ const ThresholdState next_state = g_versionbitscache.State(blockindex, consensusParams, id);
+ const ThresholdState current_state = g_versionbitscache.State(blockindex->pprev, consensusParams, id);
const bool has_signal = (ThresholdState::STARTED == current_state || ThresholdState::LOCKED_IN == current_state);
@@ -1480,14 +1480,14 @@ static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, UniValue&
// BIP9 status
bip9.pushKV("status", get_state_name(current_state));
- bip9.pushKV("since", g_versionbitscache.StateSinceHeight(active_chain_tip->pprev, consensusParams, id));
+ bip9.pushKV("since", g_versionbitscache.StateSinceHeight(blockindex->pprev, consensusParams, id));
bip9.pushKV("status-next", get_state_name(next_state));
// BIP9 signalling status, if applicable
if (has_signal) {
UniValue statsUV(UniValue::VOBJ);
std::vector<bool> signals;
- BIP9Stats statsStruct = g_versionbitscache.Statistics(active_chain_tip, consensusParams, id, &signals);
+ BIP9Stats statsStruct = g_versionbitscache.Statistics(blockindex, consensusParams, id, &signals);
statsUV.pushKV("period", statsStruct.period);
statsUV.pushKV("elapsed", statsStruct.elapsed);
statsUV.pushKV("count", statsStruct.count);
@@ -1508,7 +1508,7 @@ static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, UniValue&
UniValue rv(UniValue::VOBJ);
rv.pushKV("type", "bip9");
if (ThresholdState::ACTIVE == next_state) {
- rv.pushKV("height", g_versionbitscache.StateSinceHeight(active_chain_tip, consensusParams, id));
+ rv.pushKV("height", g_versionbitscache.StateSinceHeight(blockindex, consensusParams, id));
}
rv.pushKV("active", ThresholdState::ACTIVE == next_state);
rv.pushKV("bip9", bip9);
@@ -1517,7 +1517,7 @@ static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, UniValue&
}
namespace {
-/* TODO: when -dprecatedrpc=softforks is removed, drop these */
+/* TODO: when -deprecatedrpc=softforks is removed, drop these */
UniValue DeploymentInfo(const CBlockIndex* tip, const Consensus::Params& consensusParams);
extern const std::vector<RPCResult> RPCHelpForDeployment;
}
@@ -1621,9 +1621,9 @@ const std::vector<RPCResult> RPCHelpForDeployment{
{RPCResult::Type::NUM_TIME, "start_time", "the minimum median time past of a block at which the bit gains its meaning"},
{RPCResult::Type::NUM_TIME, "timeout", "the median time past of a block at which the deployment is considered failed if not yet locked in"},
{RPCResult::Type::NUM, "min_activation_height", "minimum height of blocks for which the rules may be enforced"},
- {RPCResult::Type::STR, "status", "bip9 status of specified block (one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\")"},
+ {RPCResult::Type::STR, "status", "status of deployment at specified block (one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\")"},
{RPCResult::Type::NUM, "since", "height of the first block to which the status applies"},
- {RPCResult::Type::STR, "status-next", "bip9 status of next block"},
+ {RPCResult::Type::STR, "status-next", "status of deployment at the next block"},
{RPCResult::Type::OBJ, "statistics", /*optional=*/true, "numeric statistics about signalling for a softfork (only for \"started\" and \"locked_in\" status)",
{
{RPCResult::Type::NUM, "period", "the length in blocks of the signalling period"},
@@ -1636,16 +1636,16 @@ const std::vector<RPCResult> RPCHelpForDeployment{
}},
};
-UniValue DeploymentInfo(const CBlockIndex* tip, const Consensus::Params& consensusParams)
+UniValue DeploymentInfo(const CBlockIndex* blockindex, const Consensus::Params& consensusParams)
{
UniValue softforks(UniValue::VOBJ);
- SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_HEIGHTINCB);
- SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_DERSIG);
- SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_CLTV);
- SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_CSV);
- SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_SEGWIT);
- SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_TESTDUMMY);
- SoftForkDescPushBack(tip, softforks, consensusParams, Consensus::DEPLOYMENT_TAPROOT);
+ SoftForkDescPushBack(blockindex, softforks, consensusParams, Consensus::DEPLOYMENT_HEIGHTINCB);
+ SoftForkDescPushBack(blockindex, softforks, consensusParams, Consensus::DEPLOYMENT_DERSIG);
+ SoftForkDescPushBack(blockindex, softforks, consensusParams, Consensus::DEPLOYMENT_CLTV);
+ SoftForkDescPushBack(blockindex, softforks, consensusParams, Consensus::DEPLOYMENT_CSV);
+ SoftForkDescPushBack(blockindex, softforks, consensusParams, Consensus::DEPLOYMENT_SEGWIT);
+ SoftForkDescPushBack(blockindex, softforks, consensusParams, Consensus::DEPLOYMENT_TESTDUMMY);
+ SoftForkDescPushBack(blockindex, softforks, consensusParams, Consensus::DEPLOYMENT_TAPROOT);
return softforks;
}
} // anon namespace
@@ -1653,9 +1653,9 @@ UniValue DeploymentInfo(const CBlockIndex* tip, const Consensus::Params& consens
static RPCHelpMan getdeploymentinfo()
{
return RPCHelpMan{"getdeploymentinfo",
- "Returns an object containing various state info regarding soft-forks.",
+ "Returns an object containing various state info regarding deployments of consensus changes.",
{
- {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Default{"chain tip"}, "The block hash at which to query fork state"},
+ {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Default{"hash of current chain tip"}, "The block hash at which to query deployment state"},
},
RPCResult{
RPCResult::Type::OBJ, "", "", {
@@ -1669,18 +1669,18 @@ static RPCHelpMan getdeploymentinfo()
RPCExamples{ HelpExampleCli("getdeploymentinfo", "") + HelpExampleRpc("getdeploymentinfo", "") },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- ChainstateManager& chainman = EnsureAnyChainman(request.context);
+ const ChainstateManager& chainman = EnsureAnyChainman(request.context);
LOCK(cs_main);
- CChainState& active_chainstate = chainman.ActiveChainstate();
+ const CChainState& active_chainstate = chainman.ActiveChainstate();
- const CBlockIndex* tip;
+ const CBlockIndex* blockindex;
if (request.params[0].isNull()) {
- tip = active_chainstate.m_chain.Tip();
- CHECK_NONFATAL(tip);
+ blockindex = active_chainstate.m_chain.Tip();
+ CHECK_NONFATAL(blockindex);
} else {
- uint256 hash(ParseHashV(request.params[0], "blockhash"));
- tip = chainman.m_blockman.LookupBlockIndex(hash);
- if (!tip) {
+ const uint256 hash(ParseHashV(request.params[0], "blockhash"));
+ blockindex = chainman.m_blockman.LookupBlockIndex(hash);
+ if (!blockindex) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
}
}
@@ -1688,9 +1688,9 @@ static RPCHelpMan getdeploymentinfo()
const Consensus::Params& consensusParams = Params().GetConsensus();
UniValue deploymentinfo(UniValue::VOBJ);
- deploymentinfo.pushKV("hash", tip->GetBlockHash().ToString());
- deploymentinfo.pushKV("height", tip->nHeight);
- deploymentinfo.pushKV("deployments", DeploymentInfo(tip, consensusParams));
+ deploymentinfo.pushKV("hash", blockindex->GetBlockHash().ToString());
+ deploymentinfo.pushKV("height", blockindex->nHeight);
+ deploymentinfo.pushKV("deployments", DeploymentInfo(blockindex, consensusParams));
return deploymentinfo;
},
};
diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json
index 724789bbf9..ad05240369 100644
--- a/src/test/data/script_tests.json
+++ b/src/test/data/script_tests.json
@@ -1269,6 +1269,10 @@
[["51", 0.00000000 ], "", "0 0x206e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", "P2SH,WITNESS", "WITNESS_PROGRAM_MISMATCH", "Witness script hash mismatch"],
[["00", 0.00000000 ], "", "0 0x206e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", "", "OK", "Invalid witness script without WITNESS"],
[["51", 0.00000000 ], "", "0 0x206e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", "", "OK", "Witness script hash mismatch without WITNESS"],
+[["51", 0.00000000 ], "", "-1 0x021234", "P2SH,WITNESS", "WITNESS_UNEXPECTED", "OP_1NEGATE does not introduce a witness program"],
+[["51", 0.00000000 ], "00", "1 0x021234", "P2SH,WITNESS", "WITNESS_MALLEATED", "OP_1 does introduce a witness program"],
+[["51", 0.00000000 ], "00", "16 0x021234", "P2SH,WITNESS", "WITNESS_MALLEATED", "OP_16 does introduce a witness program"],
+[["51", 0.00000000 ], "", "NOP 0x021234", "P2SH,WITNESS", "WITNESS_UNEXPECTED", "NOP does not introduce a witness program"],
["Automatically generated test cases"],
[
diff --git a/src/test/main.cpp b/src/test/main.cpp
index 1ad8fcce3a..73bb331e21 100644
--- a/src/test/main.cpp
+++ b/src/test/main.cpp
@@ -3,11 +3,11 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/**
- * See https://www.boost.org/doc/libs/1_71_0/libs/test/doc/html/boost_test/utf_reference/link_references/link_boost_test_module_macro.html
+ * See https://www.boost.org/doc/libs/1_78_0/libs/test/doc/html/boost_test/adv_scenarios/single_header_customizations/multiple_translation_units.html
*/
#define BOOST_TEST_MODULE Bitcoin Core Test Suite
-#include <boost/test/unit_test.hpp>
+#include <boost/test/included/unit_test.hpp>
#include <test/util/setup_common.h>
diff --git a/src/util/syscall_sandbox.cpp b/src/util/syscall_sandbox.cpp
index 4157be9d9f..f513dba598 100644
--- a/src/util/syscall_sandbox.cpp
+++ b/src/util/syscall_sandbox.cpp
@@ -600,6 +600,7 @@ public:
allowed_syscalls.insert(__NR_statfs); // get filesystem statistics
allowed_syscalls.insert(__NR_statx); // get file status (extended)
allowed_syscalls.insert(__NR_unlink); // delete a name and possibly the file it refers to
+ allowed_syscalls.insert(__NR_unlinkat); // delete relative to a directory file descriptor
}
void AllowFutex()
diff --git a/src/versionbits.cpp b/src/versionbits.cpp
index 36815fba17..7a297c2bbb 100644
--- a/src/versionbits.cpp
+++ b/src/versionbits.cpp
@@ -107,7 +107,7 @@ BIP9Stats AbstractThresholdConditionChecker::GetStateStatisticsFor(const CBlockI
if (pindex == nullptr) return stats;
- // Find beginning of period
+ // Find how many blocks are in the current period
int blocks_in_period = 1 + (pindex->nHeight % stats.period);
// Reset signalling_blocks