refactor: Make all `const static` class members `constexpr`
What changed, and why it matters
This commit is a code cleanup that changes many internal class constants from 'static const' to 'static constexpr'. In modern C++, constexpr constants are automatically inlined and avoid certain linker errors when used in specific ways. There is no functional change to Bitcoin's behavior, no bug fix, and no security-relevant change.
No security action required. Treat as normal refactoring/CI hygiene.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch converts static const integral/enum class data members to static constexpr, which makes them inline constants under C++17. This resolves potential ODR-use linker failures when such constants are passed by const reference. The change also removes an out-of-class definition in zmqabstractnotifier.cpp because constexpr static data members no longer require a separate definition. The modifications are purely compile-time/refactoring and do not alter runtime semantics.
Changed components
src/compressor.hsrc/crypto/hkdf_sha256_32.hsrc/crypto/hmac_sha256.hsrc/crypto/hmac_sha512.hsrc/crypto/ripemd160.hsrc/crypto/sha1.hsrc/crypto/sha256.hsrc/hash.hsrc/key.hsrc/node/utxo_snapshot.hsrc/policy/fees/block_policy_estimator.hsrc/primitives/transaction.hsrc/qt/recentrequeststablemodel.hsrc/qt/sendcoinsrecipient.hsrc/qt/transactionfilterproxy.hsrc/qt/transactionrecord.hsrc/script/script.hsrc/support/lockedpool.hsrc/test/scriptnum10.hsrc/tinyformat.hsrc/txmempool.hsrc/wallet/walletdb.hsrc/zmq/zmqabstractnotifier.cppsrc/zmq/zmqabstractnotifier.hInspect captured patch +38 / −40
diff --git a/src/compressor.h b/src/compressor.h
index 95490b7b..b6b738f6 100644
--- a/src/compressor.h
+++ b/src/compressor.h
@@ -59,7 +59,7 @@ struct ScriptCompression
* transactions, in which case this value becomes dependent on version
* and nHeight of the enclosing transaction.
*/
- static const unsigned int nSpecialScripts = 6;
+ static constexpr unsigned int nSpecialScripts{6};
template<typename Stream>
void Ser(Stream &s, const CScript& script) {
diff --git a/src/crypto/hkdf_sha256_32.h b/src/crypto/hkdf_sha256_32.h
index 7c5d5a7f..ec705042 100644
--- a/src/crypto/hkdf_sha256_32.h
+++ b/src/crypto/hkdf_sha256_32.h
@@ -13,7 +13,7 @@ class CHKDF_HMAC_SHA256_L32
{
private:
unsigned char m_prk[32];
- static const size_t OUTPUT_SIZE = 32;
+ static constexpr size_t OUTPUT_SIZE{32};
public:
CHKDF_HMAC_SHA256_L32(const unsigned char* ikm, size_t ikmlen, const std::string& salt);
diff --git a/src/crypto/hmac_sha256.h b/src/crypto/hmac_sha256.h
index a26947d5..0bf424c9 100644
--- a/src/crypto/hmac_sha256.h
+++ b/src/crypto/hmac_sha256.h
@@ -17,7 +17,7 @@ private:
CSHA256 inner;
public:
- static const size_t OUTPUT_SIZE = 32;
+ static constexpr size_t OUTPUT_SIZE{32};
CHMAC_SHA256(const unsigned char* key, size_t keylen);
CHMAC_SHA256& Write(const unsigned char* data, size_t len)
diff --git a/src/crypto/hmac_sha512.h b/src/crypto/hmac_sha512.h
index dfae8d05..adcfb681 100644
--- a/src/crypto/hmac_sha512.h
+++ b/src/crypto/hmac_sha512.h
@@ -17,7 +17,7 @@ private:
CSHA512 inner;
public:
- static const size_t OUTPUT_SIZE = 64;
+ static constexpr size_t OUTPUT_SIZE{64};
CHMAC_SHA512(const unsigned char* key, size_t keylen);
CHMAC_SHA512& Write(const unsigned char* data, size_t len)
diff --git a/src/crypto/ripemd160.h b/src/crypto/ripemd160.h
index a06a3255..45afc419 100644
--- a/src/crypto/ripemd160.h
+++ b/src/crypto/ripemd160.h
@@ -17,7 +17,7 @@ private:
uint64_t bytes{0};
public:
- static const size_t OUTPUT_SIZE = 20;
+ static constexpr size_t OUTPUT_SIZE{20};
CRIPEMD160();
CRIPEMD160& Write(const unsigned char* data, size_t len);
diff --git a/src/crypto/sha1.h b/src/crypto/sha1.h
index fcb96ee6..1327ccfa 100644
--- a/src/crypto/sha1.h
+++ b/src/crypto/sha1.h
@@ -17,7 +17,7 @@ private:
uint64_t bytes{0};
public:
- static const size_t OUTPUT_SIZE = 20;
+ static constexpr size_t OUTPUT_SIZE = 20;
CSHA1();
CSHA1& Write(const unsigned char* data, size_t len);
diff --git a/src/crypto/sha256.h b/src/crypto/sha256.h
index 3ac771c5..de47991e 100644
--- a/src/crypto/sha256.h
+++ b/src/crypto/sha256.h
@@ -18,7 +18,7 @@ private:
uint64_t bytes{0};
public:
- static const size_t OUTPUT_SIZE = 32;
+ static constexpr size_t OUTPUT_SIZE{32};
CSHA256();
CSHA256& Write(const unsigned char* data, size_t len);
diff --git a/src/hash.h b/src/hash.h
index b671761f..eabcf18b 100644
--- a/src/hash.h
+++ b/src/hash.h
@@ -33,7 +33,7 @@ class CHash256 {
private:
CSHA256 sha;
public:
- static const size_t OUTPUT_SIZE = CSHA256::OUTPUT_SIZE;
+ static constexpr size_t OUTPUT_SIZE{CSHA256::OUTPUT_SIZE};
void Finalize(std::span<unsigned char> output) {
assert(output.size() == OUTPUT_SIZE);
@@ -58,7 +58,7 @@ class CHash160 {
private:
CSHA256 sha;
public:
- static const size_t OUTPUT_SIZE = CRIPEMD160::OUTPUT_SIZE;
+ static constexpr size_t OUTPUT_SIZE{CRIPEMD160::OUTPUT_SIZE};
void Finalize(std::span<unsigned char> output) {
assert(output.size() == OUTPUT_SIZE);
diff --git a/src/key.h b/src/key.h
index cd77dcd0..ae95abea 100644
--- a/src/key.h
+++ b/src/key.h
@@ -39,8 +39,8 @@ public:
/**
* secp256k1:
*/
- static const unsigned int SIZE = 279;
- static const unsigned int COMPRESSED_SIZE = 214;
+ static constexpr unsigned int SIZE{279};
+ static constexpr unsigned int COMPRESSED_SIZE{214};
/**
* see www.keylength.com
* script supports up to 75 for single byte push
diff --git a/src/node/utxo_snapshot.h b/src/node/utxo_snapshot.h
index d8b3ca61..482edd3e 100644
--- a/src/node/utxo_snapshot.h
+++ b/src/node/utxo_snapshot.h
@@ -36,7 +36,7 @@ namespace node {
//! before being used. Thus, new fields should be added only if needed.
class SnapshotMetadata
{
- inline static const uint16_t VERSION{2};
+ static constexpr uint16_t VERSION{2};
const std::set<uint16_t> m_supported_versions{VERSION};
const MessageStartChars m_network_magic;
public:
diff --git a/src/policy/fees/block_policy_estimator.h b/src/policy/fees/block_policy_estimator.h
index f015bd5b..d513f15a 100644
--- a/src/policy/fees/block_policy_estimator.h
+++ b/src/policy/fees/block_policy_estimator.h
@@ -157,7 +157,7 @@ private:
static constexpr unsigned int LONG_BLOCK_PERIODS = 42;
static constexpr unsigned int LONG_SCALE = 24;
/** Historical estimates that are older than this aren't valid */
- static const unsigned int OLDEST_ESTIMATE_HISTORY = 6 * 1008;
+ static constexpr unsigned int OLDEST_ESTIMATE_HISTORY{6 * 1008};
/** Decay of .962 is a half-life of 18 blocks or about 3 hours */
static constexpr double SHORT_DECAY = .962;
diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h
index 3a7735e1..17fea5b4 100644
--- a/src/primitives/transaction.h
+++ b/src/primitives/transaction.h
@@ -73,13 +73,13 @@ public:
* it set (BIP 65).
* It has SEQUENCE_LOCKTIME_DISABLE_FLAG set (BIP 68/112).
*/
- static const uint32_t SEQUENCE_FINAL = 0xffffffff;
+ static constexpr uint32_t SEQUENCE_FINAL{0xffffffff};
/**
* This is the maximum sequence number that enables both nLockTime and
* OP_CHECKLOCKTIMEVERIFY (BIP 65).
* It has SEQUENCE_LOCKTIME_DISABLE_FLAG set (BIP 68/112).
*/
- static const uint32_t MAX_SEQUENCE_NONFINAL{SEQUENCE_FINAL - 1};
+ static constexpr uint32_t MAX_SEQUENCE_NONFINAL{SEQUENCE_FINAL - 1};
// Below flags apply in the context of BIP 68. BIP 68 requires the tx
// version to be set to 2, or higher.
@@ -90,18 +90,18 @@ public:
* It fails OP_CHECKSEQUENCEVERIFY/CheckSequence() for any input that has
* it set (BIP 112).
*/
- static const uint32_t SEQUENCE_LOCKTIME_DISABLE_FLAG = (1U << 31);
+ static constexpr uint32_t SEQUENCE_LOCKTIME_DISABLE_FLAG{1U << 31};
/**
* If CTxIn::nSequence encodes a relative lock-time and this flag
* is set, the relative lock-time has units of 512 seconds,
* otherwise it specifies blocks with a granularity of 1. */
- static const uint32_t SEQUENCE_LOCKTIME_TYPE_FLAG = (1 << 22);
+ static constexpr uint32_t SEQUENCE_LOCKTIME_TYPE_FLAG{1 << 22};
/**
* If CTxIn::nSequence encodes a relative lock-time, this mask is
* applied to extract that lock-time from the sequence field. */
- static const uint32_t SEQUENCE_LOCKTIME_MASK = 0x0000ffff;
+ static constexpr uint32_t SEQUENCE_LOCKTIME_MASK{0x0000ffff};
/**
* In order to use the same number of bits to encode roughly the
@@ -111,7 +111,7 @@ public:
* Converting from CTxIn::nSequence to seconds is performed by
* multiplying by 512 = 2^9, or equivalently shifting up by
* 9 bits. */
- static const int SEQUENCE_LOCKTIME_GRANULARITY = 9;
+ static constexpr int SEQUENCE_LOCKTIME_GRANULARITY{9};
CTxIn()
{
@@ -281,7 +281,7 @@ class CTransaction
{
public:
// Default transaction version.
- static const uint32_t CURRENT_VERSION{2};
+ static constexpr uint32_t CURRENT_VERSION{2};
// The local variables are made const to prevent unintended modification
// without updating the cached hash value. However, CTransaction is not
diff --git a/src/qt/recentrequeststablemodel.h b/src/qt/recentrequeststablemodel.h
index 31602b81..c52423be 100644
--- a/src/qt/recentrequeststablemodel.h
+++ b/src/qt/recentrequeststablemodel.h
@@ -20,7 +20,7 @@ class RecentRequestEntry
public:
RecentRequestEntry() = default;
- static const int CURRENT_VERSION = 1;
+ static constexpr int CURRENT_VERSION{1};
int nVersion{RecentRequestEntry::CURRENT_VERSION};
int64_t id{0};
QDateTime date;
diff --git a/src/qt/sendcoinsrecipient.h b/src/qt/sendcoinsrecipient.h
index 496bf689..9cc8fab8 100644
--- a/src/qt/sendcoinsrecipient.h
+++ b/src/qt/sendcoinsrecipient.h
@@ -37,7 +37,7 @@ public:
bool fSubtractFeeFromAmount; // memory only
- static const int CURRENT_VERSION = 1;
+ static constexpr int CURRENT_VERSION{1};
int nVersion;
SERIALIZE_METHODS(SendCoinsRecipient, obj)
diff --git a/src/qt/transactionfilterproxy.h b/src/qt/transactionfilterproxy.h
index f8724a9c..ee0dcf98 100644
--- a/src/qt/transactionfilterproxy.h
+++ b/src/qt/transactionfilterproxy.h
@@ -21,7 +21,7 @@ public:
explicit TransactionFilterProxy(QObject *parent = nullptr);
/** Type filter bit field (all types) */
- static const quint32 ALL_TYPES = 0xFFFFFFFF;
+ static constexpr quint32 ALL_TYPES{0xFFFFFFFF};
static quint32 TYPE(int type) { return 1<<type; }
diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h
index 7b72ff9b..714c4454 100644
--- a/src/qt/transactionrecord.h
+++ b/src/qt/transactionrecord.h
@@ -73,7 +73,7 @@ public:
};
/** Number of confirmation recommended for accepting a transaction */
- static const int RecommendedNumConfirmations = 6;
+ static constexpr int RecommendedNumConfirmations{6};
TransactionRecord():
hash(), time(0), type(Other), debit(0), credit(0), idx(0)
diff --git a/src/script/script.h b/src/script/script.h
index e0112cc3..e23ad440 100644
--- a/src/script/script.h
+++ b/src/script/script.h
@@ -241,7 +241,7 @@ public:
m_value = n;
}
- static const size_t nDefaultMaxNumSize = 4;
+ static constexpr size_t nDefaultMaxNumSize{4};
explicit CScriptNum(const std::vector<unsigned char>& vch, bool fRequireMinimal,
const size_t nMaxNumSize = nDefaultMaxNumSize)
diff --git a/src/support/lockedpool.h b/src/support/lockedpool.h
index c4966bbb..dd3c9d41 100644
--- a/src/support/lockedpool.h
+++ b/src/support/lockedpool.h
@@ -131,11 +131,11 @@ public:
* allocation and deallocation overhead. Setting it too high allocates
* more locked memory from the OS than strictly necessary.
*/
- static const size_t ARENA_SIZE = 256*1024;
+ static constexpr size_t ARENA_SIZE{256*1024};
/** Chunk alignment. Another compromise. Setting this too high will waste
* memory, setting it too low will facilitate fragmentation.
*/
- static const size_t ARENA_ALIGN = 16;
+ static constexpr size_t ARENA_ALIGN{16};
/** Callback when allocation succeeds but locking fails.
*/
diff --git a/src/test/scriptnum10.h b/src/test/scriptnum10.h
index 40260671..a49693b3 100644
--- a/src/test/scriptnum10.h
+++ b/src/test/scriptnum10.h
@@ -31,7 +31,7 @@ public:
m_value = n;
}
- static const size_t nDefaultMaxNumSize = 4;
+ static constexpr size_t nDefaultMaxNumSize{4};
explicit CScriptNum10(const std::vector<unsigned char>& vch, bool fRequireMinimal,
const size_t nMaxNumSize = nDefaultMaxNumSize)
diff --git a/src/tinyformat.h b/src/tinyformat.h
index 29b0f9e3..444cd6de 100644
--- a/src/tinyformat.h
+++ b/src/tinyformat.h
@@ -232,7 +232,7 @@ struct is_convertible
// the overload set only if the version taking a T2 doesn't match.
// Then we compare the sizes of the return types to check which
// function matched. Very neat, in a disgusting kind of way :)
- static const bool value =
+ static constexpr bool value =
sizeof(tryConvert(makeT1())) == sizeof(succeed);
# ifdef _MSC_VER
# pragma warning(pop)
diff --git a/src/txmempool.h b/src/txmempool.h
index 1a5405d5..48082cbe 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -209,7 +209,7 @@ protected:
public:
- static const int ROLLING_FEE_HALFLIFE = 60 * 60 * 12; // public only for testing
+ static constexpr int ROLLING_FEE_HALFLIFE{60 * 60 * 12}; // public only for testing
using indexed_transaction_set = boost::multi_index_container<
CTxMemPoolEntry,
diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h
index 8397fff9..76375cd9 100644
--- a/src/wallet/walletdb.h
+++ b/src/wallet/walletdb.h
@@ -100,9 +100,9 @@ public:
int64_t m_next_external_index{0}; // Next index in the keypool to be used. Memory only.
int64_t m_next_internal_index{0}; // Next index in the keypool to be used. Memory only.
- static const int VERSION_HD_BASE = 1;
- static const int VERSION_HD_CHAIN_SPLIT = 2;
- static const int CURRENT_VERSION = VERSION_HD_CHAIN_SPLIT;
+ static constexpr int VERSION_HD_BASE{1};
+ static constexpr int VERSION_HD_CHAIN_SPLIT{2};
+ static constexpr int CURRENT_VERSION{VERSION_HD_CHAIN_SPLIT};
int nVersion;
CHDChain() { SetNull(); }
@@ -136,10 +136,10 @@ public:
class CKeyMetadata
{
public:
- static const int VERSION_BASIC=1;
- static const int VERSION_WITH_HDDATA=10;
- static const int VERSION_WITH_KEY_ORIGIN = 12;
- static const int CURRENT_VERSION=VERSION_WITH_KEY_ORIGIN;
+ static constexpr int VERSION_BASIC{1};
+ static constexpr int VERSION_WITH_HDDATA{10};
+ static constexpr int VERSION_WITH_KEY_ORIGIN{12};
+ static constexpr int CURRENT_VERSION{VERSION_WITH_KEY_ORIGIN};
int nVersion;
int64_t nCreateTime; // 0 means unknown
std::string hdKeypath; //optional HD/bip32 keypath. Still used to determine whether a key is a seed. Also kept for backwards compatibility
diff --git a/src/zmq/zmqabstractnotifier.cpp b/src/zmq/zmqabstractnotifier.cpp
index 081a2a2c..77bb8a7a 100644
--- a/src/zmq/zmqabstractnotifier.cpp
+++ b/src/zmq/zmqabstractnotifier.cpp
@@ -6,8 +6,6 @@
#include <cassert>
-const int CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM;
-
CZMQAbstractNotifier::~CZMQAbstractNotifier()
{
assert(!psocket);
diff --git a/src/zmq/zmqabstractnotifier.h b/src/zmq/zmqabstractnotifier.h
index 77d478a1..686a46a1 100644
--- a/src/zmq/zmqabstractnotifier.h
+++ b/src/zmq/zmqabstractnotifier.h
@@ -19,7 +19,7 @@ using CZMQNotifierFactory = std::function<std::unique_ptr<CZMQAbstractNotifier>(
class CZMQAbstractNotifier
{
public:
- static const int DEFAULT_ZMQ_SNDHWM {1000};
+ static constexpr int DEFAULT_ZMQ_SNDHWM {1000};
virtual ~CZMQAbstractNotifier();
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.