Skip to content

Commit

Permalink
addrdb: Only call Serialize() once
Browse files Browse the repository at this point in the history
The previous logic would call it once for serializing into the filestream,
and then again for serializing into the hasher. If AddrMan was changed
in between these calls by another thread, the resulting peers.dat would
be corrupt with non-matching checksum and data.
Fix this by using HashedSourceWriter, which writes the data
to the underlying stream and keeps track of the hash in one go.

Github-Pull: #26909
Rebased-From: 5eabb61
  • Loading branch information
mzumsande authored and fanquake committed Feb 20, 2023
1 parent 91f83db commit 07397cd
Show file tree
Hide file tree
Showing 2 changed files with 4 additions and 6 deletions.
7 changes: 3 additions & 4 deletions src/addrdb.cpp
Expand Up @@ -34,10 +34,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());
}
Expand Down
3 changes: 1 addition & 2 deletions src/addrman.cpp
Expand Up @@ -1178,8 +1178,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);
Expand Down

0 comments on commit 07397cd

Please sign in to comment.