Skip to content

Commit e484652

Browse files
committed
Introduce CHashVerifier to hash read data
This is necessary later, when we drop the nVersion field from the undo data. At that point deserializing and reserializing the data won't roundtrip anymore, and thus that approach can't be used to verify checksums anymore. With this CHashVerifier approach, we can deserialize while hashing the exact serialized form that was used. This is both more efficient and more correct in that case.
1 parent f54580e commit e484652

File tree

2 files changed

+39
-5
lines changed

2 files changed

+39
-5
lines changed

src/hash.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,41 @@ class CHashWriter
160160
}
161161
};
162162

163+
/** Reads data from an underlying stream, while hashing the read data. */
164+
template<typename Source>
165+
class CHashVerifier : public CHashWriter
166+
{
167+
private:
168+
Source* source;
169+
170+
public:
171+
CHashVerifier(Source* source_) : CHashWriter(source_->GetType(), source_->GetVersion()), source(source_) {}
172+
173+
void read(char* pch, size_t nSize)
174+
{
175+
source->read(pch, nSize);
176+
this->write(pch, nSize);
177+
}
178+
179+
void ignore(size_t nSize)
180+
{
181+
char data[1024];
182+
while (nSize > 0) {
183+
size_t now = std::min<size_t>(nSize, 1024);
184+
read(data, now);
185+
nSize -= now;
186+
}
187+
}
188+
189+
template<typename T>
190+
CHashVerifier<Source>& operator>>(T& obj)
191+
{
192+
// Unserialize from this stream
193+
::Unserialize(*this, obj);
194+
return (*this);
195+
}
196+
};
197+
163198
/** Compute the 256-bit hash of an object's serialization. */
164199
template<typename T>
165200
uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION)

src/validation.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,19 +1210,18 @@ bool UndoReadFromDisk(CBlockUndo& blockundo, const CDiskBlockPos& pos, const uin
12101210

12111211
// Read block
12121212
uint256 hashChecksum;
1213+
CHashVerifier<CAutoFile> verifier(&filein); // We need a CHashVerifier as reserializing may lose data
12131214
try {
1214-
filein >> blockundo;
1215+
verifier << hashBlock;
1216+
verifier >> blockundo;
12151217
filein >> hashChecksum;
12161218
}
12171219
catch (const std::exception& e) {
12181220
return error("%s: Deserialize or I/O error - %s", __func__, e.what());
12191221
}
12201222

12211223
// Verify checksum
1222-
CHashWriter hasher(SER_GETHASH, PROTOCOL_VERSION);
1223-
hasher << hashBlock;
1224-
hasher << blockundo;
1225-
if (hashChecksum != hasher.GetHash())
1224+
if (hashChecksum != verifier.GetHash())
12261225
return error("%s: Checksum mismatch", __func__);
12271226

12281227
return true;

0 commit comments

Comments
 (0)