From 37e2b011136ca1cf00dfb9e575d12f0d035a6a2c Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Wed, 2 Aug 2023 10:24:20 +0200 Subject: [PATCH 1/7] [refactor] Allow std::array in serialize.h This is already possible for C-style arrays, so allow it for C++11 std::array as well. --- src/serialize.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/serialize.h b/src/serialize.h index 2d790190a0b..f1595077e91 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -285,6 +285,7 @@ template inline void Serialize(Stream& s, int64_t a ) { ser_wri template inline void Serialize(Stream& s, uint64_t a) { ser_writedata64(s, a); } template inline void Serialize(Stream& s, const char (&a)[N]) { s.write(MakeByteSpan(a)); } template inline void Serialize(Stream& s, const unsigned char (&a)[N]) { s.write(MakeByteSpan(a)); } +template void Serialize(Stream& s, const std::array& a) { (void)/* force byte-type */UCharCast(a.data()); s.write(MakeByteSpan(a)); } template void Serialize(Stream& s, Span span) { (void)/* force byte-type */UCharCast(span.data()); s.write(AsBytes(span)); } #ifndef CHAR_EQUALS_INT8 @@ -301,6 +302,7 @@ template inline void Unserialize(Stream& s, int64_t& a ) { a = template inline void Unserialize(Stream& s, uint64_t& a) { a = ser_readdata64(s); } template inline void Unserialize(Stream& s, char (&a)[N]) { s.read(MakeWritableByteSpan(a)); } template inline void Unserialize(Stream& s, unsigned char (&a)[N]) { s.read(MakeWritableByteSpan(a)); } +template void Unserialize(Stream& s, std::array& a) { (void)/* force byte-type */UCharCast(a.data()); s.read(MakeWritableByteSpan(a)); } template void Unserialize(Stream& s, Span span) { (void)/* force byte-type */UCharCast(span.data()); s.read(AsWritableBytes(span)); } template inline void Serialize(Stream& s, bool a) { uint8_t f = a; ser_writedata8(s, f); } From 9be330b654cfbd792620295f3867f592059d6a7a Mon Sep 17 00:00:00 2001 From: TheCharlatan Date: Tue, 12 Sep 2023 13:01:07 +0200 Subject: [PATCH 2/7] [refactor] Define MessageStartChars as std::array --- src/addrdb.cpp | 4 ++-- src/kernel/chainparams.cpp | 2 +- src/net.cpp | 6 +++--- src/node/blockstorage.cpp | 2 +- src/node/blockstorage.h | 2 +- src/protocol.cpp | 2 +- src/protocol.h | 10 +++++----- src/validation.cpp | 4 ++-- src/wallet/db.cpp | 2 +- src/wallet/sqlite.cpp | 4 ++-- 10 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/addrdb.cpp b/src/addrdb.cpp index c5b474339b9..6b21d3a1ed9 100644 --- a/src/addrdb.cpp +++ b/src/addrdb.cpp @@ -90,10 +90,10 @@ void DeserializeDB(Stream& stream, Data&& data, bool fCheckSum = true) { HashVerifier verifier{stream}; // de-serialize file header (network specific magic number) and .. - unsigned char pchMsgTmp[4]; + CMessageHeader::MessageStartChars pchMsgTmp; verifier >> pchMsgTmp; // ... verify the network matches ours - if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp))) { + if (pchMsgTmp != Params().MessageStart()) { throw std::runtime_error{"Invalid network magic number"}; } diff --git a/src/kernel/chainparams.cpp b/src/kernel/chainparams.cpp index 733a3339b38..c41559ad98f 100644 --- a/src/kernel/chainparams.cpp +++ b/src/kernel/chainparams.cpp @@ -359,7 +359,7 @@ public: HashWriter h{}; h << consensus.signet_challenge; uint256 hash = h.GetHash(); - memcpy(pchMessageStart, hash.begin(), 4); + std::copy_n(hash.begin(), 4, pchMessageStart.begin()); nDefaultPort = 38333; nPruneAfterHeight = 1000; diff --git a/src/net.cpp b/src/net.cpp index af2855932de..d091db74c4a 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -730,7 +730,7 @@ V1Transport::V1Transport(const NodeId node_id, int nTypeIn, int nVersionIn) noex m_node_id(node_id), hdrbuf(nTypeIn, nVersionIn), vRecv(nTypeIn, nVersionIn) { assert(std::size(Params().MessageStart()) == std::size(m_magic_bytes)); - std::copy(std::begin(Params().MessageStart()), std::end(Params().MessageStart()), m_magic_bytes); + m_magic_bytes = Params().MessageStart(); LOCK(m_recv_mutex); Reset(); } @@ -759,7 +759,7 @@ int V1Transport::readHeader(Span msg_bytes) } // Check start string, network magic - if (memcmp(hdr.pchMessageStart, m_magic_bytes, CMessageHeader::MESSAGE_START_SIZE) != 0) { + if (hdr.pchMessageStart != m_magic_bytes) { LogPrint(BCLog::NET, "Header error: Wrong MessageStart %s received, peer=%d\n", HexStr(hdr.pchMessageStart), m_node_id); return -1; } @@ -1144,7 +1144,7 @@ bool V2Transport::ProcessReceivedKeyBytes() noexcept // they receive our uniformly random key and garbage, but detecting this case specially // means we can log it. static constexpr std::array MATCH = {'v', 'e', 'r', 's', 'i', 'o', 'n', 0, 0, 0, 0, 0}; - static constexpr size_t OFFSET = sizeof(CMessageHeader::MessageStartChars); + static constexpr size_t OFFSET = std::tuple_size_v; if (!m_initiating && m_recv_buffer.size() >= OFFSET + MATCH.size()) { if (std::equal(MATCH.begin(), MATCH.end(), m_recv_buffer.begin() + OFFSET)) { LogPrint(BCLog::NET, "V2 transport error: V1 peer with wrong MessageStart %s\n", diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp index 70f11be5861..2e4e077f187 100644 --- a/src/node/blockstorage.cpp +++ b/src/node/blockstorage.cpp @@ -932,7 +932,7 @@ bool BlockManager::ReadRawBlockFromDisk(std::vector& block, const FlatF filein >> blk_start >> blk_size; - if (memcmp(blk_start, GetParams().MessageStart(), CMessageHeader::MESSAGE_START_SIZE)) { + if (blk_start != GetParams().MessageStart()) { return error("%s: Block magic mismatch for %s: %s versus expected %s", __func__, pos.ToString(), HexStr(blk_start), HexStr(GetParams().MessageStart())); diff --git a/src/node/blockstorage.h b/src/node/blockstorage.h index c79fd2c6a14..4b57637427f 100644 --- a/src/node/blockstorage.h +++ b/src/node/blockstorage.h @@ -73,7 +73,7 @@ static const unsigned int UNDOFILE_CHUNK_SIZE = 0x100000; // 1 MiB static const unsigned int MAX_BLOCKFILE_SIZE = 0x8000000; // 128 MiB /** Size of header written by WriteBlockToDisk before a serialized CBlock */ -static constexpr size_t BLOCK_SERIALIZATION_HEADER_SIZE = CMessageHeader::MESSAGE_START_SIZE + sizeof(unsigned int); +static constexpr size_t BLOCK_SERIALIZATION_HEADER_SIZE = std::tuple_size_v + sizeof(unsigned int); extern std::atomic_bool fReindex; diff --git a/src/protocol.cpp b/src/protocol.cpp index 2105480c72a..cb956191e4d 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -92,7 +92,7 @@ const static std::vector g_all_net_message_types{ CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn, const char* pszCommand, unsigned int nMessageSizeIn) { - memcpy(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE); + pchMessageStart = pchMessageStartIn; // Copy the command name size_t i = 0; diff --git a/src/protocol.h b/src/protocol.h index a7ca0c6f3e3..cb7f9666e14 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -26,14 +27,13 @@ class CMessageHeader { public: - static constexpr size_t MESSAGE_START_SIZE = 4; + using MessageStartChars = std::array; static constexpr size_t COMMAND_SIZE = 12; static constexpr size_t MESSAGE_SIZE_SIZE = 4; static constexpr size_t CHECKSUM_SIZE = 4; - static constexpr size_t MESSAGE_SIZE_OFFSET = MESSAGE_START_SIZE + COMMAND_SIZE; + static constexpr size_t MESSAGE_SIZE_OFFSET = std::tuple_size_v + COMMAND_SIZE; static constexpr size_t CHECKSUM_OFFSET = MESSAGE_SIZE_OFFSET + MESSAGE_SIZE_SIZE; - static constexpr size_t HEADER_SIZE = MESSAGE_START_SIZE + COMMAND_SIZE + MESSAGE_SIZE_SIZE + CHECKSUM_SIZE; - typedef unsigned char MessageStartChars[MESSAGE_START_SIZE]; + static constexpr size_t HEADER_SIZE = std::tuple_size_v + COMMAND_SIZE + MESSAGE_SIZE_SIZE + CHECKSUM_SIZE; explicit CMessageHeader() = default; @@ -47,7 +47,7 @@ public: SERIALIZE_METHODS(CMessageHeader, obj) { READWRITE(obj.pchMessageStart, obj.pchCommand, obj.nMessageSize, obj.pchChecksum); } - char pchMessageStart[MESSAGE_START_SIZE]{}; + MessageStartChars pchMessageStart{}; char pchCommand[COMMAND_SIZE]{}; uint32_t nMessageSize{std::numeric_limits::max()}; uint8_t pchChecksum[CHECKSUM_SIZE]{}; diff --git a/src/validation.cpp b/src/validation.cpp index e3a00e4241e..4bb648d1e5b 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -4533,11 +4533,11 @@ void ChainstateManager::LoadExternalBlockFile( unsigned int nSize = 0; try { // locate a header - unsigned char buf[CMessageHeader::MESSAGE_START_SIZE]; + CMessageHeader::MessageStartChars buf; blkdat.FindByte(std::byte(params.MessageStart()[0])); nRewind = blkdat.GetPos() + 1; blkdat >> buf; - if (memcmp(buf, params.MessageStart(), CMessageHeader::MESSAGE_START_SIZE)) { + if (buf != params.MessageStart()) { continue; } // read size diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index 0c249205162..0ee39d2b5a6 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -136,7 +136,7 @@ bool IsSQLiteFile(const fs::path& path) } // Check the application id matches our network magic - return memcmp(Params().MessageStart(), app_id, 4) == 0; + return memcmp(Params().MessageStart().data(), app_id, 4) == 0; } void ReadDatabaseArgs(const ArgsManager& args, DatabaseOptions& options) diff --git a/src/wallet/sqlite.cpp b/src/wallet/sqlite.cpp index ecd34bb96a6..db9989163df 100644 --- a/src/wallet/sqlite.cpp +++ b/src/wallet/sqlite.cpp @@ -193,7 +193,7 @@ bool SQLiteDatabase::Verify(bilingual_str& error) auto read_result = ReadPragmaInteger(m_db, "application_id", "the application id", error); if (!read_result.has_value()) return false; uint32_t app_id = static_cast(read_result.value()); - uint32_t net_magic = ReadBE32(Params().MessageStart()); + uint32_t net_magic = ReadBE32(Params().MessageStart().data()); if (app_id != net_magic) { error = strprintf(_("SQLiteDatabase: Unexpected application id. Expected %u, got %u"), net_magic, app_id); return false; @@ -324,7 +324,7 @@ void SQLiteDatabase::Open() } // Set the application id - uint32_t app_id = ReadBE32(Params().MessageStart()); + uint32_t app_id = ReadBE32(Params().MessageStart().data()); SetPragma(m_db, "application_id", strprintf("%d", static_cast(app_id)), "Failed to set the application id"); From 534b314a7401d44f51aabd4565f97be9ee411740 Mon Sep 17 00:00:00 2001 From: TheCharlatan Date: Wed, 6 Sep 2023 15:55:14 +0200 Subject: [PATCH 3/7] kernel: Move MessageStartChars to its own file The protocol.h file contains many non-consensus related definitions and should thus not be part of the libbitcoinkernel. This commit makes protocol.h no longer a required include for users of the libbitcoinkernel. This commit is part of the libbitcoinkernel project, namely its stage 1 step 3: Decouple most non-consensus headers from libbitcoinkernel. Co-Authored-By: Cory Fields --- src/Makefile.am | 1 + src/addrdb.cpp | 2 +- src/kernel/chainparams.cpp | 1 + src/kernel/chainparams.h | 6 +++--- src/kernel/messagestartchars.h | 13 +++++++++++++ src/net.cpp | 2 +- src/net.h | 5 +++-- src/node/blockstorage.cpp | 3 ++- src/node/blockstorage.h | 4 ++-- src/protocol.h | 2 +- src/test/net_tests.cpp | 2 +- src/validation.cpp | 3 ++- 12 files changed, 31 insertions(+), 13 deletions(-) create mode 100644 src/kernel/messagestartchars.h diff --git a/src/Makefile.am b/src/Makefile.am index feed4a0061c..e542a067a47 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -191,6 +191,7 @@ BITCOIN_CORE_H = \ kernel/mempool_options.h \ kernel/mempool_persist.h \ kernel/mempool_removal_reason.h \ + kernel/messagestartchars.h \ kernel/notifications_interface.h \ kernel/validation_cache_sizes.h \ key.h \ diff --git a/src/addrdb.cpp b/src/addrdb.cpp index 6b21d3a1ed9..50f576624c6 100644 --- a/src/addrdb.cpp +++ b/src/addrdb.cpp @@ -90,7 +90,7 @@ void DeserializeDB(Stream& stream, Data&& data, bool fCheckSum = true) { HashVerifier verifier{stream}; // de-serialize file header (network specific magic number) and .. - CMessageHeader::MessageStartChars pchMsgTmp; + MessageStartChars pchMsgTmp; verifier >> pchMsgTmp; // ... verify the network matches ours if (pchMsgTmp != Params().MessageStart()) { diff --git a/src/kernel/chainparams.cpp b/src/kernel/chainparams.cpp index c41559ad98f..6cee379faf9 100644 --- a/src/kernel/chainparams.cpp +++ b/src/kernel/chainparams.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include diff --git a/src/kernel/chainparams.h b/src/kernel/chainparams.h index 2d38af609c9..f1df878f60b 100644 --- a/src/kernel/chainparams.h +++ b/src/kernel/chainparams.h @@ -7,9 +7,9 @@ #define BITCOIN_KERNEL_CHAINPARAMS_H #include +#include #include #include -#include #include #include #include @@ -87,7 +87,7 @@ public: }; const Consensus::Params& GetConsensus() const { return consensus; } - const CMessageHeader::MessageStartChars& MessageStart() const { return pchMessageStart; } + const MessageStartChars& MessageStart() const { return pchMessageStart; } uint16_t GetDefaultPort() const { return nDefaultPort; } uint16_t GetDefaultPort(Network net) const { @@ -165,7 +165,7 @@ protected: CChainParams() {} Consensus::Params consensus; - CMessageHeader::MessageStartChars pchMessageStart; + MessageStartChars pchMessageStart; uint16_t nDefaultPort; uint64_t nPruneAfterHeight; uint64_t m_assumed_blockchain_size; diff --git a/src/kernel/messagestartchars.h b/src/kernel/messagestartchars.h new file mode 100644 index 00000000000..829616dc8bd --- /dev/null +++ b/src/kernel/messagestartchars.h @@ -0,0 +1,13 @@ +// Copyright (c) 2023 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_KERNEL_MESSAGESTARTCHARS_H +#define BITCOIN_KERNEL_MESSAGESTARTCHARS_H + +#include +#include + +using MessageStartChars = std::array; + +#endif // BITCOIN_KERNEL_MESSAGESTARTCHARS_H diff --git a/src/net.cpp b/src/net.cpp index d091db74c4a..ddbf9a6e3c3 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1144,7 +1144,7 @@ bool V2Transport::ProcessReceivedKeyBytes() noexcept // they receive our uniformly random key and garbage, but detecting this case specially // means we can log it. static constexpr std::array MATCH = {'v', 'e', 'r', 's', 'i', 'o', 'n', 0, 0, 0, 0, 0}; - static constexpr size_t OFFSET = std::tuple_size_v; + static constexpr size_t OFFSET = std::tuple_size_v; if (!m_initiating && m_recv_buffer.size() >= OFFSET + MATCH.size()) { if (std::equal(MATCH.begin(), MATCH.end(), m_recv_buffer.begin() + OFFSET)) { LogPrint(BCLog::NET, "V2 transport error: V1 peer with wrong MessageStart %s\n", diff --git a/src/net.h b/src/net.h index e1d8995a8eb..669ff68cb4b 100644 --- a/src/net.h +++ b/src/net.h @@ -10,15 +10,16 @@ #include #include #include -#include #include #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -360,7 +361,7 @@ public: class V1Transport final : public Transport { private: - CMessageHeader::MessageStartChars m_magic_bytes; + MessageStartChars m_magic_bytes; const NodeId m_node_id; // Only for logging mutable Mutex m_recv_mutex; //!< Lock for receive state mutable CHash256 hasher GUARDED_BY(m_recv_mutex); diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp index 2e4e077f187..253dee088e7 100644 --- a/src/node/blockstorage.cpp +++ b/src/node/blockstorage.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -927,7 +928,7 @@ bool BlockManager::ReadRawBlockFromDisk(std::vector& block, const FlatF } try { - CMessageHeader::MessageStartChars blk_start; + MessageStartChars blk_start; unsigned int blk_size; filein >> blk_start >> blk_size; diff --git a/src/node/blockstorage.h b/src/node/blockstorage.h index 4b57637427f..b251ece31f2 100644 --- a/src/node/blockstorage.h +++ b/src/node/blockstorage.h @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include @@ -73,7 +73,7 @@ static const unsigned int UNDOFILE_CHUNK_SIZE = 0x100000; // 1 MiB static const unsigned int MAX_BLOCKFILE_SIZE = 0x8000000; // 128 MiB /** Size of header written by WriteBlockToDisk before a serialized CBlock */ -static constexpr size_t BLOCK_SERIALIZATION_HEADER_SIZE = std::tuple_size_v + sizeof(unsigned int); +static constexpr size_t BLOCK_SERIALIZATION_HEADER_SIZE = std::tuple_size_v + sizeof(unsigned int); extern std::atomic_bool fReindex; diff --git a/src/protocol.h b/src/protocol.h index cb7f9666e14..22e2108afb1 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -6,6 +6,7 @@ #ifndef BITCOIN_PROTOCOL_H #define BITCOIN_PROTOCOL_H +#include // IWYU pragma: export #include #include #include @@ -27,7 +28,6 @@ class CMessageHeader { public: - using MessageStartChars = std::array; static constexpr size_t COMMAND_SIZE = 12; static constexpr size_t MESSAGE_SIZE_SIZE = 4; static constexpr size_t CHECKSUM_SIZE = 4; diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index 3eb7bdec62f..34d78670793 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -1114,7 +1114,7 @@ public: } /** Send V1 version message header to the transport. */ - void SendV1Version(const CMessageHeader::MessageStartChars& magic) + void SendV1Version(const MessageStartChars& magic) { CMessageHeader hdr(magic, "version", 126 + InsecureRandRange(11)); CDataStream ser(SER_NETWORK, CLIENT_VERSION); diff --git a/src/validation.cpp b/src/validation.cpp index 4bb648d1e5b..8d4b8386e80 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -4533,7 +4534,7 @@ void ChainstateManager::LoadExternalBlockFile( unsigned int nSize = 0; try { // locate a header - CMessageHeader::MessageStartChars buf; + MessageStartChars buf; blkdat.FindByte(std::byte(params.MessageStart()[0])); nRewind = blkdat.GetPos() + 1; blkdat >> buf; From f0d1d8b35c3aa9f2f923f74e3dbbf1e5ece4cd2f Mon Sep 17 00:00:00 2001 From: TheCharlatan Date: Wed, 6 Sep 2023 16:59:32 +0200 Subject: [PATCH 4/7] [refactor] Add missing includes for next commit --- src/bench/block_assemble.cpp | 1 + src/bench/duplicate_inputs.cpp | 1 + src/bench/mempool_stress.cpp | 1 + src/bitcoin-chainstate.cpp | 1 + src/bitcoin-util.cpp | 1 + src/key_io.cpp | 1 + src/node/blockstorage.cpp | 1 + src/test/fuzz/descriptor_parse.cpp | 1 + src/test/txvalidationcache_tests.cpp | 1 + 9 files changed, 9 insertions(+) diff --git a/src/bench/block_assemble.cpp b/src/bench/block_assemble.cpp index 4d032cefc5f..0737144b84f 100644 --- a/src/bench/block_assemble.cpp +++ b/src/bench/block_assemble.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include diff --git a/src/bench/duplicate_inputs.cpp b/src/bench/duplicate_inputs.cpp index b3799ad1b72..a1c8d4d9420 100644 --- a/src/bench/duplicate_inputs.cpp +++ b/src/bench/duplicate_inputs.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include diff --git a/src/bench/mempool_stress.cpp b/src/bench/mempool_stress.cpp index 1f94461d198..993db666531 100644 --- a/src/bench/mempool_stress.cpp +++ b/src/bench/mempool_stress.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include diff --git a/src/bitcoin-chainstate.cpp b/src/bitcoin-chainstate.cpp index 19c4d36126e..fc83a4ad3a3 100644 --- a/src/bitcoin-chainstate.cpp +++ b/src/bitcoin-chainstate.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include