From 56f1b2d01c01ce053313b2ac5c1b0214606c1399 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <6098974-kittywhiskers@users.noreply.gitlab.com> Date: Wed, 19 May 2021 21:09:18 +0530 Subject: [PATCH] Partial #19326: Simplify hash.h interface using Spans --- src/bench/chacha_poly_aead.cpp | 2 +- src/bench/crypto_hash.cpp | 16 +++++++------- src/blockfilter.cpp | 8 +++---- src/hash.cpp | 2 +- src/hash.h | 38 ++++++++++++++++++---------------- src/key.cpp | 2 +- src/net.cpp | 4 ++-- src/script/interpreter.cpp | 4 ++-- src/span.h | 12 +++++++++++ src/test/crypto_tests.cpp | 2 +- src/test/merkle_tests.cpp | 6 +++--- src/uint256.cpp | 10 ++++----- src/uint256.h | 33 +++++++++++++++-------------- 13 files changed, 78 insertions(+), 61 deletions(-) diff --git a/src/bench/chacha_poly_aead.cpp b/src/bench/chacha_poly_aead.cpp index f5f7297490..cd2802ef06 100644 --- a/src/bench/chacha_poly_aead.cpp +++ b/src/bench/chacha_poly_aead.cpp @@ -94,7 +94,7 @@ static void HASH(benchmark::State& state, size_t buffersize) uint8_t hash[CHash256::OUTPUT_SIZE]; std::vector in(buffersize,0); while (state.KeepRunning()) - CHash256().Write(in.data(), in.size()).Finalize(hash); + CHash256().Write(in).Finalize(hash); } static void HASH_64BYTES(benchmark::State& state) diff --git a/src/bench/crypto_hash.cpp b/src/bench/crypto_hash.cpp index 584702c850..4d339c38cb 100644 --- a/src/bench/crypto_hash.cpp +++ b/src/bench/crypto_hash.cpp @@ -58,14 +58,14 @@ static void HASH_DSHA256(benchmark::State& state) uint8_t hash[CSHA256::OUTPUT_SIZE]; std::vector in(BUFFER_SIZE,0); while (state.KeepRunning()) - CHash256().Write(in.data(), in.size()).Finalize(hash); + CHash256().Write(in).Finalize(hash); } static void HASH_DSHA256_0032b(benchmark::State& state) { std::vector in(32,0); while (state.KeepRunning()) { - CHash256().Write(in.data(), in.size()).Finalize(in.data()); + CHash256().Write(in).Finalize(in); } } @@ -116,42 +116,42 @@ static void HASH_DSHA256_0032b_single(benchmark::State& state) { std::vector in(32,0); while (state.KeepRunning()) - CHash256().Write(in.data(), in.size()).Finalize(in.data()); + CHash256().Write(in).Finalize(in); } static void HASH_DSHA256_0080b_single(benchmark::State& state) { std::vector in(80,0); while (state.KeepRunning()) - CHash256().Write(in.data(), in.size()).Finalize(in.data()); + CHash256().Write(in).Finalize(in); } static void HASH_DSHA256_0128b_single(benchmark::State& state) { std::vector in(128,0); while (state.KeepRunning()) - CHash256().Write(in.data(), in.size()).Finalize(in.data()); + CHash256().Write(in).Finalize(in); } static void HASH_DSHA256_0512b_single(benchmark::State& state) { std::vector in(512,0); while (state.KeepRunning()) - CHash256().Write(in.data(), in.size()).Finalize(in.data()); + CHash256().Write(in).Finalize(in); } static void HASH_DSHA256_1024b_single(benchmark::State& state) { std::vector in(1024,0); while (state.KeepRunning()) - CHash256().Write(in.data(), in.size()).Finalize(in.data()); + CHash256().Write(in).Finalize(in); } static void HASH_DSHA256_2048b_single(benchmark::State& state) { std::vector in(2048,0); while (state.KeepRunning()) - CHash256().Write(in.data(), in.size()).Finalize(in.data()); + CHash256().Write(in).Finalize(in); } static void HASH_X11(benchmark::State& state) diff --git a/src/blockfilter.cpp b/src/blockfilter.cpp index 7ada6b025b..271104fc62 100644 --- a/src/blockfilter.cpp +++ b/src/blockfilter.cpp @@ -244,7 +244,7 @@ uint256 BlockFilter::GetHash() const const std::vector& data = GetEncodedFilter(); uint256 result; - CHash256().Write(data.data(), data.size()).Finalize(result.begin()); + CHash256().Write(data).Finalize(result); return result; } @@ -254,8 +254,8 @@ uint256 BlockFilter::ComputeHeader(const uint256& prev_header) const uint256 result; CHash256() - .Write(filter_hash.begin(), filter_hash.size()) - .Write(prev_header.begin(), prev_header.size()) - .Finalize(result.begin()); + .Write(filter_hash) + .Write(prev_header) + .Finalize(result); return result; } diff --git a/src/hash.cpp b/src/hash.cpp index 33e772c4dc..ee0281f9eb 100644 --- a/src/hash.cpp +++ b/src/hash.cpp @@ -12,7 +12,7 @@ inline uint32_t ROTL32(uint32_t x, int8_t r) return (x << r) | (x >> (32 - r)); } -unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector& vDataToHash) +unsigned int MurmurHash3(unsigned int nHashSeed, Span vDataToHash) { // The following is MurmurHash3 (x86_32), see http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp uint32_t h1 = nHashSeed; diff --git a/src/hash.h b/src/hash.h index aaff1ba8cc..1a6401e672 100644 --- a/src/hash.h +++ b/src/hash.h @@ -38,14 +38,15 @@ private: public: static const size_t OUTPUT_SIZE = CSHA256::OUTPUT_SIZE; - void Finalize(unsigned char hash[OUTPUT_SIZE]) { + void Finalize(Span output) { + assert(output.size() == OUTPUT_SIZE); unsigned char buf[CSHA256::OUTPUT_SIZE]; sha.Finalize(buf); - sha.Reset().Write(buf, CSHA256::OUTPUT_SIZE).Finalize(hash); + sha.Reset().Write(buf, CSHA256::OUTPUT_SIZE).Finalize(output.data()); } - CHash256& Write(const unsigned char *data, size_t len) { - sha.Write(data, len); + CHash256& Write(Span input) { + sha.Write(input.data(), input.size()); return *this; } @@ -62,14 +63,15 @@ private: public: static const size_t OUTPUT_SIZE = CRIPEMD160::OUTPUT_SIZE; - void Finalize(unsigned char hash[OUTPUT_SIZE]) { + void Finalize(Span output) { + assert(output.size() == OUTPUT_SIZE); unsigned char buf[CSHA256::OUTPUT_SIZE]; sha.Finalize(buf); - CRIPEMD160().Write(buf, CSHA256::OUTPUT_SIZE).Finalize(hash); + CRIPEMD160().Write(buf, CSHA256::OUTPUT_SIZE).Finalize(output.data()); } - CHash160& Write(const unsigned char *data, size_t len) { - sha.Write(data, len); + CHash160& Write(Span input) { + sha.Write(input.data(), input.size()); return *this; } @@ -85,8 +87,8 @@ inline uint256 Hash(const T1 pbegin, const T1 pend) { static const unsigned char pblank[1] = {}; uint256 result; - CHash256().Write(pbegin == pend ? pblank : (const unsigned char*)&pbegin[0], (pend - pbegin) * sizeof(pbegin[0])) - .Finalize((unsigned char*)&result); + CHash256().Write({pbegin == pend ? pblank : (const unsigned char*)&pbegin[0], (pend - pbegin) * sizeof(pbegin[0])}) + .Finalize(result); return result; } @@ -96,9 +98,9 @@ inline uint256 Hash(const T1 p1begin, const T1 p1end, const T2 p2begin, const T2 p2end) { static const unsigned char pblank[1] = {}; uint256 result; - CHash256().Write(p1begin == p1end ? pblank : (const unsigned char*)&p1begin[0], (p1end - p1begin) * sizeof(p1begin[0])) - .Write(p2begin == p2end ? pblank : (const unsigned char*)&p2begin[0], (p2end - p2begin) * sizeof(p2begin[0])) - .Finalize((unsigned char*)&result); + CHash256().Write({p1begin == p1end ? pblank : (const unsigned char*)&p1begin[0], (p1end - p1begin) * sizeof(p1begin[0])}) + .Write({p2begin == p2end ? pblank : (const unsigned char*)&p2begin[0], (p2end - p2begin) * sizeof(p2begin[0])}) + .Finalize(result); return result; } @@ -162,8 +164,8 @@ inline uint160 Hash160(const T1 pbegin, const T1 pend) { static unsigned char pblank[1] = {}; uint160 result; - CHash160().Write(pbegin == pend ? pblank : (const unsigned char*)&pbegin[0], (pend - pbegin) * sizeof(pbegin[0])) - .Finalize((unsigned char*)&result); + CHash160().Write({pbegin == pend ? pblank : (const unsigned char*)&pbegin[0], (pend - pbegin) * sizeof(pbegin[0])}) + .Finalize(result); return result; } @@ -196,13 +198,13 @@ public: int GetVersion() const { return nVersion; } void write(const char *pch, size_t size) { - ctx.Write((const unsigned char*)pch, size); + ctx.Write({(const unsigned char*)pch, size}); } // invalidates the object uint256 GetHash() { uint256 result; - ctx.Finalize((unsigned char*)&result); + ctx.Finalize(result); return result; } @@ -258,7 +260,7 @@ uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL return ss.GetHash(); } -unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector& vDataToHash); +unsigned int MurmurHash3(unsigned int nHashSeed, Span vDataToHash); void BIP32Hash(const ChainCode &chainCode, unsigned int nChild, unsigned char header, const unsigned char data[32], unsigned char output[64]); diff --git a/src/key.cpp b/src/key.cpp index 3ae873c97f..a75d56618d 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -212,7 +212,7 @@ bool CKey::VerifyPubKey(const CPubKey& pubkey) const { std::string str = "Bitcoin key verification\n"; GetRandBytes(rnd, sizeof(rnd)); uint256 hash; - CHash256().Write((unsigned char*)str.data(), str.size()).Write(rnd, sizeof(rnd)).Finalize(hash.begin()); + CHash256().Write(MakeUCharSpan(str)).Write(rnd).Finalize(hash); std::vector vchSig; Sign(hash, vchSig); return pubkey.Verify(hash, vchSig); diff --git a/src/net.cpp b/src/net.cpp index 29cde6714b..363f178693 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -948,7 +948,7 @@ int CNetMessage::readData(const char *pch, unsigned int nBytes) vRecv.resize(std::min(hdr.nMessageSize, nDataPos + nCopy + 256 * 1024)); } - hasher.Write((const unsigned char*)pch, nCopy); + hasher.Write({(const unsigned char*)pch, nCopy}); memcpy(&vRecv[nDataPos], pch, nCopy); nDataPos += nCopy; @@ -959,7 +959,7 @@ const uint256& CNetMessage::GetMessageHash() const { assert(complete()); if (data_hash.IsNull()) - hasher.Finalize(data_hash.begin()); + hasher.Finalize(data_hash); return data_hash; } diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 5c32505a90..9ca4a62379 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -934,9 +934,9 @@ bool EvalScript(std::vector >& stack, const CScript& else if (opcode == OP_SHA256) CSHA256().Write(vch.data(), vch.size()).Finalize(vchHash.data()); else if (opcode == OP_HASH160) - CHash160().Write(vch.data(), vch.size()).Finalize(vchHash.data()); + CHash160().Write(vch).Finalize(vchHash); else if (opcode == OP_HASH256) - CHash256().Write(vch.data(), vch.size()).Finalize(vchHash.data()); + CHash256().Write(vch).Finalize(vchHash); popstack(stack); stack.push_back(vchHash); } diff --git a/src/span.h b/src/span.h index 88a078e902..c423e49d8e 100644 --- a/src/span.h +++ b/src/span.h @@ -179,4 +179,16 @@ T& SpanPopBack(Span& span) return back; } +// Helper functions to safely cast to unsigned char pointers. +inline unsigned char* UCharCast(char* c) { return (unsigned char*)c; } +inline unsigned char* UCharCast(unsigned char* c) { return c; } +inline const unsigned char* UCharCast(const char* c) { return (unsigned char*)c; } +inline const unsigned char* UCharCast(const unsigned char* c) { return c; } + +// Helper function to safely convert a Span to a Span<[const] unsigned char>. +template constexpr auto UCharSpanCast(Span s) -> Span::type> { return {UCharCast(s.data()), s.size()}; } + +/** Like MakeSpan, but for (const) unsigned char member types only. Only works for (un)signed char containers. */ +template constexpr auto MakeUCharSpan(V&& v) -> decltype(UCharSpanCast(MakeSpan(std::forward(v)))) { return UCharSpanCast(MakeSpan(std::forward(v))); } + #endif diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index da2c760920..baafbbfffa 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -817,7 +817,7 @@ BOOST_AUTO_TEST_CASE(sha256d64) in[j] = InsecureRandBits(8); } for (int j = 0; j < i; ++j) { - CHash256().Write(in + 64 * j, 64).Finalize(out1 + 32 * j); + CHash256().Write({in + 64 * j, 64}).Finalize({out1 + 32 * j, 32}); } SHA256D64(out2, in, i); BOOST_CHECK(memcmp(out1, out2, 32 * i) == 0); diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp index 6e54578ca6..11a8517e95 100644 --- a/src/test/merkle_tests.cpp +++ b/src/test/merkle_tests.cpp @@ -60,7 +60,7 @@ static void MerkleComputation(const std::vector& leaves, uint256* proot } } mutated |= (inner[level] == h); - CHash256().Write(inner[level].begin(), 32).Write(h.begin(), 32).Finalize(h.begin()); + CHash256().Write(inner[level]).Write(h).Finalize(h); } // Store the resulting hash at inner position level. inner[level] = h; @@ -86,7 +86,7 @@ static void MerkleComputation(const std::vector& leaves, uint256* proot if (pbranch && matchh) { pbranch->push_back(h); } - CHash256().Write(h.begin(), 32).Write(h.begin(), 32).Finalize(h.begin()); + CHash256().Write(h).Write(h).Finalize(h); // Increment count to the value it would have if two entries at this // level had existed. count += (((uint32_t)1) << level); @@ -101,7 +101,7 @@ static void MerkleComputation(const std::vector& leaves, uint256* proot matchh = true; } } - CHash256().Write(inner[level].begin(), 32).Write(h.begin(), 32).Finalize(h.begin()); + CHash256().Write(inner[level]).Write(h).Finalize(h); level++; } } diff --git a/src/uint256.cpp b/src/uint256.cpp index 0d3f187d48..9afda5c5a0 100644 --- a/src/uint256.cpp +++ b/src/uint256.cpp @@ -13,8 +13,8 @@ template base_blob::base_blob(const std::vector& vch) { - assert(vch.size() == sizeof(data)); - memcpy(data, vch.data(), sizeof(data)); + assert(vch.size() == sizeof(m_data)); + memcpy(m_data, vch.data(), sizeof(m_data)); } template @@ -22,7 +22,7 @@ std::string base_blob::GetHex() const { uint8_t m_data_rev[WIDTH]; for (int i = 0; i < WIDTH; ++i) { - m_data_rev[i] = data[WIDTH - 1 - i]; + m_data_rev[i] = m_data[WIDTH - 1 - i]; } return HexStr(m_data_rev); } @@ -30,7 +30,7 @@ std::string base_blob::GetHex() const template void base_blob::SetHex(const char* psz) { - memset(data, 0, sizeof(data)); + memset(m_data, 0, sizeof(m_data)); // skip leading spaces while (isspace(*psz)) @@ -45,7 +45,7 @@ void base_blob::SetHex(const char* psz) while (::HexDigit(*psz) != -1) psz++; psz--; - unsigned char* p1 = (unsigned char*)data; + unsigned char* p1 = (unsigned char*)m_data; unsigned char* pend = p1 + WIDTH; while (psz >= pbegin && p1 < pend) { *p1 = ::HexDigit(*psz--); diff --git a/src/uint256.h b/src/uint256.h index 405446d10d..cfb00635bf 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -21,11 +21,11 @@ class base_blob { protected: static constexpr int WIDTH = BITS / 8; - uint8_t data[WIDTH]; + uint8_t m_data[WIDTH]; public: base_blob() { - memset(data, 0, sizeof(data)); + memset(m_data, 0, sizeof(m_data)); } explicit base_blob(const std::vector& vch); @@ -33,17 +33,17 @@ public: bool IsNull() const { for (int i = 0; i < WIDTH; i++) - if (data[i] != 0) + if (m_data[i] != 0) return false; return true; } void SetNull() { - memset(data, 0, sizeof(data)); + memset(m_data, 0, sizeof(m_data)); } - inline int Compare(const base_blob& other) const { return memcmp(data, other.data, sizeof(data)); } + inline int Compare(const base_blob& other) const { return memcmp(m_data, other.m_data, sizeof(m_data)); } friend inline bool operator==(const base_blob& a, const base_blob& b) { return a.Compare(b) == 0; } friend inline bool operator!=(const base_blob& a, const base_blob& b) { return a.Compare(b) != 0; } @@ -54,34 +54,37 @@ public: void SetHex(const std::string& str); std::string ToString() const; + const unsigned char* data() const { return m_data; } + unsigned char* data() { return m_data; } + unsigned char* begin() { - return &data[0]; + return &m_data[0]; } unsigned char* end() { - return &data[WIDTH]; + return &m_data[WIDTH]; } const unsigned char* begin() const { - return &data[0]; + return &m_data[0]; } const unsigned char* end() const { - return &data[WIDTH]; + return &m_data[WIDTH]; } unsigned int size() const { - return sizeof(data); + return sizeof(m_data); } uint64_t GetUint64(int pos) const { - const uint8_t* ptr = data + pos * 8; + const uint8_t* ptr = m_data + pos * 8; return ((uint64_t)ptr[0]) | \ ((uint64_t)ptr[1]) << 8 | \ ((uint64_t)ptr[2]) << 16 | \ @@ -95,13 +98,13 @@ public: template void Serialize(Stream& s) const { - s.write((char*)data, sizeof(data)); + s.write((char*)m_data, sizeof(m_data)); } template void Unserialize(Stream& s) { - s.read((char*)data, sizeof(data)); + s.read((char*)m_data, sizeof(m_data)); } }; @@ -132,7 +135,7 @@ public: */ uint64_t GetCheapHash() const { - return ReadLE64(data); + return ReadLE64(m_data); } }; @@ -167,7 +170,7 @@ public: uint256 trim256() const { uint256 result; - memcpy((void*)&result, (void*)data, 32); + memcpy((void*)&result, (void*)m_data, 32); return result; } };