Skip to content

Commit 34eb236

Browse files
committed
Merge bitcoin#19326: Simplify hash.h interface using Spans
77c5073 Make Hash[160] consume range-like objects (Pieter Wuille) 02c4cc5 Make CHash256/CHash160 output to Span (Pieter Wuille) 0ef97b1 Make MurmurHash3 consume Spans (Pieter Wuille) e549bf8 Make CHash256 and CHash160 consume Spans (Pieter Wuille) 2a2182c Make script/standard's BaseHash Span-convertible (Pieter Wuille) e63dcc3 Add MakeUCharSpan, to help constructing Span<[const] unsigned char> (Pieter Wuille) 5678250 Make uint256 Span-convertible by adding ::data() (Pieter Wuille) 131a2f0 scripted-diff: rename base_blob::data to m_data (Pieter Wuille) Pull request description: This makes use of the implicit constructions and conversions to Span introduced in bitcoin#18468 to simplify the hash.h interface: * All functions that take a pointer and a length are changed to take a Span instead. * The Hash() and Hash160() functions are changed to take in "range" objects instead of begin/end iterators. ACKs for top commit: laanwj: re-ACK 77c5073 jonatack: Code review re-ACK 77c5073 per `git range-diff 14ceddd 49fc016 77c5073` Tree-SHA512: 9ec929891b1ddcf30eb14b946ee1bf142eca1442b9de0067ad6a3c181e0c7ea0c99c0e291e7f6e7a18bd7bdf78fe94ee3d5de66e167401674caf91e026269771
2 parents 14ceddd + 77c5073 commit 34eb236

31 files changed

+117
-120
lines changed

src/base58.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn)
141141
{
142142
// add 4-byte hash check to the end
143143
std::vector<unsigned char> vch(vchIn);
144-
uint256 hash = Hash(vch.begin(), vch.end());
144+
uint256 hash = Hash(vch);
145145
vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
146146
return EncodeBase58(vch);
147147
}
@@ -154,7 +154,7 @@ bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet, int
154154
return false;
155155
}
156156
// re-calculate the checksum, ensure it matches the included 4-byte checksum
157-
uint256 hash = Hash(vchRet.begin(), vchRet.end() - 4);
157+
uint256 hash = Hash(MakeSpan(vchRet).first(vchRet.size() - 4));
158158
if (memcmp(&hash, &vchRet[vchRet.size() - 4], 4) != 0) {
159159
vchRet.clear();
160160
return false;

src/bench/chacha_poly_aead.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ static void HASH(benchmark::Bench& bench, size_t buffersize)
9393
uint8_t hash[CHash256::OUTPUT_SIZE];
9494
std::vector<uint8_t> in(buffersize,0);
9595
bench.batch(in.size()).unit("byte").run([&] {
96-
CHash256().Write(in.data(), in.size()).Finalize(hash);
96+
CHash256().Write(in).Finalize(hash);
9797
});
9898
}
9999

src/bench/verify_script.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ static void VerifyScriptBench(benchmark::Bench& bench)
3434
key.Set(vchKey.begin(), vchKey.end(), false);
3535
CPubKey pubkey = key.GetPubKey();
3636
uint160 pubkeyHash;
37-
CHash160().Write(pubkey.begin(), pubkey.size()).Finalize(pubkeyHash.begin());
37+
CHash160().Write(pubkey).Finalize(pubkeyHash);
3838

3939
// Script.
4040
CScript scriptPubKey = CScript() << witnessversion << ToByteVector(pubkeyHash);

src/blockfilter.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ uint256 BlockFilter::GetHash() const
291291
const std::vector<unsigned char>& data = GetEncodedFilter();
292292

293293
uint256 result;
294-
CHash256().Write(data.data(), data.size()).Finalize(result.begin());
294+
CHash256().Write(data).Finalize(result);
295295
return result;
296296
}
297297

@@ -301,8 +301,8 @@ uint256 BlockFilter::ComputeHeader(const uint256& prev_header) const
301301

302302
uint256 result;
303303
CHash256()
304-
.Write(filter_hash.begin(), filter_hash.size())
305-
.Write(prev_header.begin(), prev_header.size())
306-
.Finalize(result.begin());
304+
.Write(filter_hash)
305+
.Write(prev_header)
306+
.Finalize(result);
307307
return result;
308308
}

src/hash.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ inline uint32_t ROTL32(uint32_t x, int8_t r)
1212
return (x << r) | (x >> (32 - r));
1313
}
1414

15-
unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char>& vDataToHash)
15+
unsigned int MurmurHash3(unsigned int nHashSeed, Span<const unsigned char> vDataToHash)
1616
{
1717
// The following is MurmurHash3 (x86_32), see http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp
1818
uint32_t h1 = nHashSeed;

src/hash.h

+20-39
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,15 @@ class CHash256 {
2525
public:
2626
static const size_t OUTPUT_SIZE = CSHA256::OUTPUT_SIZE;
2727

28-
void Finalize(unsigned char hash[OUTPUT_SIZE]) {
28+
void Finalize(Span<unsigned char> output) {
29+
assert(output.size() == OUTPUT_SIZE);
2930
unsigned char buf[CSHA256::OUTPUT_SIZE];
3031
sha.Finalize(buf);
31-
sha.Reset().Write(buf, CSHA256::OUTPUT_SIZE).Finalize(hash);
32+
sha.Reset().Write(buf, CSHA256::OUTPUT_SIZE).Finalize(output.data());
3233
}
3334

34-
CHash256& Write(const unsigned char *data, size_t len) {
35-
sha.Write(data, len);
35+
CHash256& Write(Span<const unsigned char> input) {
36+
sha.Write(input.data(), input.size());
3637
return *this;
3738
}
3839

@@ -49,14 +50,15 @@ class CHash160 {
4950
public:
5051
static const size_t OUTPUT_SIZE = CRIPEMD160::OUTPUT_SIZE;
5152

52-
void Finalize(unsigned char hash[OUTPUT_SIZE]) {
53+
void Finalize(Span<unsigned char> output) {
54+
assert(output.size() == OUTPUT_SIZE);
5355
unsigned char buf[CSHA256::OUTPUT_SIZE];
5456
sha.Finalize(buf);
55-
CRIPEMD160().Write(buf, CSHA256::OUTPUT_SIZE).Finalize(hash);
57+
CRIPEMD160().Write(buf, CSHA256::OUTPUT_SIZE).Finalize(output.data());
5658
}
5759

58-
CHash160& Write(const unsigned char *data, size_t len) {
59-
sha.Write(data, len);
60+
CHash160& Write(Span<const unsigned char> input) {
61+
sha.Write(input.data(), input.size());
6062
return *this;
6163
}
6264

@@ -67,52 +69,31 @@ class CHash160 {
6769
};
6870

6971
/** Compute the 256-bit hash of an object. */
70-
template<typename T1>
71-
inline uint256 Hash(const T1 pbegin, const T1 pend)
72+
template<typename T>
73+
inline uint256 Hash(const T& in1)
7274
{
73-
static const unsigned char pblank[1] = {};
7475
uint256 result;
75-
CHash256().Write(pbegin == pend ? pblank : (const unsigned char*)&pbegin[0], (pend - pbegin) * sizeof(pbegin[0]))
76-
.Finalize((unsigned char*)&result);
76+
CHash256().Write(MakeUCharSpan(in1)).Finalize(result);
7777
return result;
7878
}
7979

8080
/** Compute the 256-bit hash of the concatenation of two objects. */
8181
template<typename T1, typename T2>
82-
inline uint256 Hash(const T1 p1begin, const T1 p1end,
83-
const T2 p2begin, const T2 p2end) {
84-
static const unsigned char pblank[1] = {};
82+
inline uint256 Hash(const T1& in1, const T2& in2) {
8583
uint256 result;
86-
CHash256().Write(p1begin == p1end ? pblank : (const unsigned char*)&p1begin[0], (p1end - p1begin) * sizeof(p1begin[0]))
87-
.Write(p2begin == p2end ? pblank : (const unsigned char*)&p2begin[0], (p2end - p2begin) * sizeof(p2begin[0]))
88-
.Finalize((unsigned char*)&result);
84+
CHash256().Write(MakeUCharSpan(in1)).Write(MakeUCharSpan(in2)).Finalize(result);
8985
return result;
9086
}
9187

9288
/** Compute the 160-bit hash an object. */
9389
template<typename T1>
94-
inline uint160 Hash160(const T1 pbegin, const T1 pend)
90+
inline uint160 Hash160(const T1& in1)
9591
{
96-
static unsigned char pblank[1] = {};
9792
uint160 result;
98-
CHash160().Write(pbegin == pend ? pblank : (const unsigned char*)&pbegin[0], (pend - pbegin) * sizeof(pbegin[0]))
99-
.Finalize((unsigned char*)&result);
93+
CHash160().Write(MakeUCharSpan(in1)).Finalize(result);
10094
return result;
10195
}
10296

103-
/** Compute the 160-bit hash of a vector. */
104-
inline uint160 Hash160(const std::vector<unsigned char>& vch)
105-
{
106-
return Hash160(vch.begin(), vch.end());
107-
}
108-
109-
/** Compute the 160-bit hash of a vector. */
110-
template<unsigned int N>
111-
inline uint160 Hash160(const prevector<N, unsigned char>& vch)
112-
{
113-
return Hash160(vch.begin(), vch.end());
114-
}
115-
11697
/** A writer stream (for serialization) that computes a 256-bit hash. */
11798
class CHashWriter
11899
{
@@ -129,13 +110,13 @@ class CHashWriter
129110
int GetVersion() const { return nVersion; }
130111

131112
void write(const char *pch, size_t size) {
132-
ctx.Write((const unsigned char*)pch, size);
113+
ctx.Write({(const unsigned char*)pch, size});
133114
}
134115

135116
// invalidates the object
136117
uint256 GetHash() {
137118
uint256 result;
138-
ctx.Finalize((unsigned char*)&result);
119+
ctx.Finalize(result);
139120
return result;
140121
}
141122

@@ -200,7 +181,7 @@ uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL
200181
return ss.GetHash();
201182
}
202183

203-
unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char>& vDataToHash);
184+
unsigned int MurmurHash3(unsigned int nHashSeed, Span<const unsigned char> vDataToHash);
204185

205186
void BIP32Hash(const ChainCode &chainCode, unsigned int nChild, unsigned char header, const unsigned char data[32], unsigned char output[64]);
206187

src/key.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ bool CKey::VerifyPubKey(const CPubKey& pubkey) const {
237237
std::string str = "Bitcoin key verification\n";
238238
GetRandBytes(rnd, sizeof(rnd));
239239
uint256 hash;
240-
CHash256().Write((unsigned char*)str.data(), str.size()).Write(rnd, sizeof(rnd)).Finalize(hash.begin());
240+
CHash256().Write(MakeUCharSpan(str)).Write(rnd).Finalize(hash);
241241
std::vector<unsigned char> vchSig;
242242
Sign(hash, vchSig);
243243
return pubkey.Verify(hash, vchSig);

src/merkleblock.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ uint256 CPartialMerkleTree::CalcHash(int height, unsigned int pos, const std::ve
7070
else
7171
right = left;
7272
// combine subhashes
73-
return Hash(left.begin(), left.end(), right.begin(), right.end());
73+
return Hash(left, right);
7474
}
7575
}
7676

@@ -126,7 +126,7 @@ uint256 CPartialMerkleTree::TraverseAndExtract(int height, unsigned int pos, uns
126126
right = left;
127127
}
128128
// and combine them before returning
129-
return Hash(left.begin(), left.end(), right.begin(), right.end());
129+
return Hash(left, right);
130130
}
131131
}
132132

src/net.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -685,7 +685,7 @@ int V1TransportDeserializer::readData(const char *pch, unsigned int nBytes)
685685
vRecv.resize(std::min(hdr.nMessageSize, nDataPos + nCopy + 256 * 1024));
686686
}
687687

688-
hasher.Write((const unsigned char*)pch, nCopy);
688+
hasher.Write({(const unsigned char*)pch, nCopy});
689689
memcpy(&vRecv[nDataPos], pch, nCopy);
690690
nDataPos += nCopy;
691691

@@ -696,7 +696,7 @@ const uint256& V1TransportDeserializer::GetMessageHash() const
696696
{
697697
assert(Complete());
698698
if (data_hash.IsNull())
699-
hasher.Finalize(data_hash.begin());
699+
hasher.Finalize(data_hash);
700700
return data_hash;
701701
}
702702

@@ -736,7 +736,7 @@ CNetMessage V1TransportDeserializer::GetMessage(const CMessageHeader::MessageSta
736736

737737
void V1TransportSerializer::prepareForTransport(CSerializedNetMsg& msg, std::vector<unsigned char>& header) {
738738
// create dbl-sha256 checksum
739-
uint256 hash = Hash(msg.data.begin(), msg.data.end());
739+
uint256 hash = Hash(msg.data);
740740

741741
// create header
742742
CMessageHeader hdr(Params().MessageStart(), msg.m_type.c_str(), msg.data.size());

src/netaddress.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,7 @@ std::vector<unsigned char> CNetAddr::GetGroup(const std::vector<bool> &asmap) co
553553

554554
uint64_t CNetAddr::GetHash() const
555555
{
556-
uint256 hash = Hash(&ip[0], &ip[16]);
556+
uint256 hash = Hash(ip);
557557
uint64_t nRet;
558558
memcpy(&nRet, &hash, sizeof(nRet));
559559
return nRet;

src/pubkey.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -157,13 +157,13 @@ class CPubKey
157157
//! Get the KeyID of this public key (hash of its serialization)
158158
CKeyID GetID() const
159159
{
160-
return CKeyID(Hash160(vch, vch + size()));
160+
return CKeyID(Hash160(MakeSpan(vch).first(size())));
161161
}
162162

163163
//! Get the 256-bit hash of this public key.
164164
uint256 GetHash() const
165165
{
166-
return Hash(vch, vch + size());
166+
return Hash(MakeSpan(vch).first(size()));
167167
}
168168

169169
/*

src/rpc/rawtransaction.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,7 @@ static UniValue decodescript(const JSONRPCRequest& request)
601601
UniValue sr(UniValue::VOBJ);
602602
CScript segwitScr;
603603
if (which_type == TxoutType::PUBKEY) {
604-
segwitScr = GetScriptForDestination(WitnessV0KeyHash(Hash160(solutions_data[0].begin(), solutions_data[0].end())));
604+
segwitScr = GetScriptForDestination(WitnessV0KeyHash(Hash160(solutions_data[0])));
605605
} else if (which_type == TxoutType::PUBKEYHASH) {
606606
segwitScr = GetScriptForDestination(WitnessV0KeyHash(uint160{solutions_data[0]}));
607607
} else {

src/script/interpreter.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -986,9 +986,9 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
986986
else if (opcode == OP_SHA256)
987987
CSHA256().Write(vch.data(), vch.size()).Finalize(vchHash.data());
988988
else if (opcode == OP_HASH160)
989-
CHash160().Write(vch.data(), vch.size()).Finalize(vchHash.data());
989+
CHash160().Write(vch).Finalize(vchHash);
990990
else if (opcode == OP_HASH256)
991-
CHash256().Write(vch.data(), vch.size()).Finalize(vchHash.data());
991+
CHash256().Write(vch).Finalize(vchHash);
992992
popstack(stack);
993993
stack.push_back(vchHash);
994994
}

src/script/standard.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ typedef std::vector<unsigned char> valtype;
1616
bool fAcceptDatacarrier = DEFAULT_ACCEPT_DATACARRIER;
1717
unsigned nMaxDatacarrierBytes = MAX_OP_RETURN_RELAY;
1818

19-
CScriptID::CScriptID(const CScript& in) : BaseHash(Hash160(in.begin(), in.end())) {}
19+
CScriptID::CScriptID(const CScript& in) : BaseHash(Hash160(in)) {}
2020
CScriptID::CScriptID(const ScriptHash& in) : BaseHash(static_cast<uint160>(in)) {}
2121

22-
ScriptHash::ScriptHash(const CScript& in) : BaseHash(Hash160(in.begin(), in.end())) {}
22+
ScriptHash::ScriptHash(const CScript& in) : BaseHash(Hash160(in)) {}
2323
ScriptHash::ScriptHash(const CScriptID& in) : BaseHash(static_cast<uint160>(in)) {}
2424

2525
PKHash::PKHash(const CPubKey& pubkey) : BaseHash(pubkey.GetID()) {}
@@ -318,7 +318,7 @@ CScript GetScriptForWitness(const CScript& redeemscript)
318318
std::vector<std::vector<unsigned char> > vSolutions;
319319
TxoutType typ = Solver(redeemscript, vSolutions);
320320
if (typ == TxoutType::PUBKEY) {
321-
return GetScriptForDestination(WitnessV0KeyHash(Hash160(vSolutions[0].begin(), vSolutions[0].end())));
321+
return GetScriptForDestination(WitnessV0KeyHash(Hash160(vSolutions[0])));
322322
} else if (typ == TxoutType::PUBKEYHASH) {
323323
return GetScriptForDestination(WitnessV0KeyHash(uint160{vSolutions[0]}));
324324
}

src/script/standard.h

+3
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ class BaseHash
7979
{
8080
return m_hash.size();
8181
}
82+
83+
unsigned char* data() { return m_hash.data(); }
84+
const unsigned char* data() const { return m_hash.data(); }
8285
};
8386

8487
/** A reference to a CScript: the Hash160 of its serialization (see script.h) */

src/span.h

+12
Original file line numberDiff line numberDiff line change
@@ -207,4 +207,16 @@ T& SpanPopBack(Span<T>& span)
207207
return back;
208208
}
209209

210+
// Helper functions to safely cast to unsigned char pointers.
211+
inline unsigned char* UCharCast(char* c) { return (unsigned char*)c; }
212+
inline unsigned char* UCharCast(unsigned char* c) { return c; }
213+
inline const unsigned char* UCharCast(const char* c) { return (unsigned char*)c; }
214+
inline const unsigned char* UCharCast(const unsigned char* c) { return c; }
215+
216+
// Helper function to safely convert a Span to a Span<[const] unsigned char>.
217+
template <typename T> constexpr auto UCharSpanCast(Span<T> s) -> Span<typename std::remove_pointer<decltype(UCharCast(s.data()))>::type> { return {UCharCast(s.data()), s.size()}; }
218+
219+
/** Like MakeSpan, but for (const) unsigned char member types only. Only works for (un)signed char containers. */
220+
template <typename V> constexpr auto MakeUCharSpan(V&& v) -> decltype(UCharSpanCast(MakeSpan(std::forward<V>(v)))) { return UCharSpanCast(MakeSpan(std::forward<V>(v))); }
221+
210222
#endif

src/test/crypto_tests.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -743,7 +743,7 @@ BOOST_AUTO_TEST_CASE(sha256d64)
743743
in[j] = InsecureRandBits(8);
744744
}
745745
for (int j = 0; j < i; ++j) {
746-
CHash256().Write(in + 64 * j, 64).Finalize(out1 + 32 * j);
746+
CHash256().Write({in + 64 * j, 64}).Finalize({out1 + 32 * j, 32});
747747
}
748748
SHA256D64(out2, in, i);
749749
BOOST_CHECK(memcmp(out1, out2, 32 * i) == 0);

src/test/fuzz/crypto.cpp

+5-6
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ void test_one_input(const std::vector<uint8_t>& buffer)
4444
}
4545
}
4646

47-
(void)hash160.Write(data.data(), data.size());
48-
(void)hash256.Write(data.data(), data.size());
47+
(void)hash160.Write(data);
48+
(void)hash256.Write(data);
4949
(void)hmac_sha256.Write(data.data(), data.size());
5050
(void)hmac_sha512.Write(data.data(), data.size());
5151
(void)ripemd160.Write(data.data(), data.size());
@@ -54,9 +54,8 @@ void test_one_input(const std::vector<uint8_t>& buffer)
5454
(void)sha512.Write(data.data(), data.size());
5555
(void)sip_hasher.Write(data.data(), data.size());
5656

57-
(void)Hash(data.begin(), data.end());
57+
(void)Hash(data);
5858
(void)Hash160(data);
59-
(void)Hash160(data.begin(), data.end());
6059
(void)sha512.Size();
6160
break;
6261
}
@@ -73,12 +72,12 @@ void test_one_input(const std::vector<uint8_t>& buffer)
7372
switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 8)) {
7473
case 0: {
7574
data.resize(CHash160::OUTPUT_SIZE);
76-
hash160.Finalize(data.data());
75+
hash160.Finalize(data);
7776
break;
7877
}
7978
case 1: {
8079
data.resize(CHash256::OUTPUT_SIZE);
81-
hash256.Finalize(data.data());
80+
hash256.Finalize(data);
8281
break;
8382
}
8483
case 2: {

src/test/fuzz/key.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
8585
assert(negated_key == key);
8686
}
8787

88-
const uint256 random_uint256 = Hash(buffer.begin(), buffer.end());
88+
const uint256 random_uint256 = Hash(buffer);
8989

9090
{
9191
CKey child_key;

0 commit comments

Comments
 (0)