mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 12:02:48 +01:00
merge bitcoin#26909: prevent peers.dat corruptions by only serializing once
This commit is contained in:
parent
4a520991db
commit
fbb2b51d75
@ -33,10 +33,9 @@ bool SerializeDB(Stream& stream, const Data& data)
|
||||
{
|
||||
// Write and commit header, data
|
||||
try {
|
||||
CHashWriter hasher(stream.GetType(), stream.GetVersion());
|
||||
stream << Params().MessageStart() << data;
|
||||
hasher << Params().MessageStart() << data;
|
||||
stream << hasher.GetHash();
|
||||
HashedSourceWriter hashwriter{stream};
|
||||
hashwriter << Params().MessageStart() << data;
|
||||
stream << hashwriter.GetHash();
|
||||
} catch (const std::exception& e) {
|
||||
return error("%s: Serialize or I/O error - %s", __func__, e.what());
|
||||
}
|
||||
|
@ -1168,8 +1168,7 @@ void AddrMan::Unserialize(Stream& s_)
|
||||
}
|
||||
|
||||
// explicit instantiation
|
||||
template void AddrMan::Serialize(CHashWriter& s) const;
|
||||
template void AddrMan::Serialize(CAutoFile& s) const;
|
||||
template void AddrMan::Serialize(HashedSourceWriter<CAutoFile>& s) const;
|
||||
template void AddrMan::Serialize(CDataStream& s) const;
|
||||
template void AddrMan::Unserialize(CAutoFile& s);
|
||||
template void AddrMan::Unserialize(CHashVerifier<CAutoFile>& s);
|
||||
|
24
src/hash.h
24
src/hash.h
@ -201,6 +201,30 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/** Writes data to an underlying source stream, while hashing the written data. */
|
||||
template <typename Source>
|
||||
class HashedSourceWriter : public CHashWriter
|
||||
{
|
||||
private:
|
||||
Source& m_source;
|
||||
|
||||
public:
|
||||
explicit HashedSourceWriter(Source& source LIFETIMEBOUND) : CHashWriter{source.GetType(), source.GetVersion()}, m_source{source} {}
|
||||
|
||||
void write(Span<const std::byte> src)
|
||||
{
|
||||
m_source.write(src);
|
||||
CHashWriter::write(src);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
HashedSourceWriter& operator<<(const T& obj)
|
||||
{
|
||||
::Serialize(*this, obj);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
/** Compute the 256-bit hash of an object's serialization. */
|
||||
template<typename T>
|
||||
uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION)
|
||||
|
@ -437,4 +437,18 @@ BOOST_AUTO_TEST_CASE(streams_buffered_file_rand)
|
||||
fs::remove("streams_test_tmp");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(streams_hashed)
|
||||
{
|
||||
CDataStream stream(SER_NETWORK, INIT_PROTO_VERSION);
|
||||
HashedSourceWriter hash_writer{stream};
|
||||
const std::string data{"bitcoin"};
|
||||
hash_writer << data;
|
||||
|
||||
CHashVerifier hash_verifier{&stream};
|
||||
std::string result;
|
||||
hash_verifier >> result;
|
||||
BOOST_CHECK_EQUAL(data, result);
|
||||
BOOST_CHECK_EQUAL(hash_writer.GetHash(), hash_verifier.GetHash());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
Loading…
Reference in New Issue
Block a user