Skip to content
25 changes: 12 additions & 13 deletions src/addrdb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,16 @@ bool SerializeDB(Stream& stream, const Data& data)
}

template <typename Data>
bool SerializeFileDB(const std::string& prefix, const fs::path& path, const Data& data, int version)
bool SerializeFileDB(const std::string& prefix, const fs::path& path, const Data& data)
{
// Generate random temporary filename
const uint16_t randv{GetRand<uint16_t>()};
std::string tmpfn = strprintf("%s.%04x", prefix, randv);

// open temp output file, and associate with CAutoFile
// open temp output file
fs::path pathTmp = gArgs.GetDataDirNet() / fs::u8path(tmpfn);
FILE *file = fsbridge::fopen(pathTmp, "wb");
CAutoFile fileout(file, SER_DISK, version);
AutoFile fileout{file};
if (fileout.IsNull()) {
fileout.fclose();
remove(pathTmp);
Expand Down Expand Up @@ -85,9 +85,9 @@ bool SerializeFileDB(const std::string& prefix, const fs::path& path, const Data
}

template <typename Stream, typename Data>
void DeserializeDB(Stream& stream, Data& data, bool fCheckSum = true)
void DeserializeDB(Stream& stream, Data&& data, bool fCheckSum = true)
{
CHashVerifier<Stream> verifier(&stream);
HashVerifier verifier{stream};
// de-serialize file header (network specific magic number) and ..
unsigned char pchMsgTmp[4];
verifier >> pchMsgTmp;
Expand All @@ -110,11 +110,10 @@ void DeserializeDB(Stream& stream, Data& data, bool fCheckSum = true)
}

template <typename Data>
void DeserializeFileDB(const fs::path& path, Data& data, int version)
void DeserializeFileDB(const fs::path& path, Data&& data)
{
// open input file, and associate with CAutoFile
FILE* file = fsbridge::fopen(path, "rb");
CAutoFile filein(file, SER_DISK, version);
AutoFile filein{file};
if (filein.IsNull()) {
throw DbNotFoundError{};
}
Expand Down Expand Up @@ -174,10 +173,10 @@ bool CBanDB::Read(banmap_t& banSet)
bool DumpPeerAddresses(const ArgsManager& args, const AddrMan& addr)
{
const auto pathAddr = gArgs.GetDataDirNet() / "peers.dat";
return SerializeFileDB("peers", pathAddr, addr, CLIENT_VERSION);
return SerializeFileDB("peers", pathAddr, addr);
}

void ReadFromStream(AddrMan& addr, CDataStream& ssPeers)
void ReadFromStream(AddrMan& addr, DataStream& ssPeers)
{
DeserializeDB(ssPeers, addr, false);
}
Expand All @@ -190,7 +189,7 @@ std::optional<bilingual_str> LoadAddrman(const NetGroupManager& netgroupman, con
const auto start{SteadyClock::now()};
const auto path_addr{gArgs.GetDataDirNet() / "peers.dat"};
try {
DeserializeFileDB(path_addr, *addrman, CLIENT_VERSION);
DeserializeFileDB(path_addr, *addrman);
LogPrintf("Loaded %i addresses from peers.dat %dms\n", addrman->Size(), Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
} catch (const DbNotFoundError&) {
// Addrman can be in an inconsistent state after failure, reset it
Expand Down Expand Up @@ -226,14 +225,14 @@ std::optional<bilingual_str> LoadAddrman(const NetGroupManager& netgroupman, con
void DumpAnchors(const fs::path& anchors_db_path, const std::vector<CAddress>& anchors)
{
LOG_TIME_SECONDS(strprintf("Flush %d outbound block-relay-only peer addresses to anchors.dat", anchors.size()));
SerializeFileDB("anchors", anchors_db_path, anchors, CLIENT_VERSION | ADDRV2_FORMAT);
SerializeFileDB("anchors", anchors_db_path, WithParams(CAddress::V2_DISK, anchors));
}

std::vector<CAddress> ReadAnchors(const fs::path& anchors_db_path)
{
std::vector<CAddress> anchors;
try {
DeserializeFileDB(anchors_db_path, anchors, CLIENT_VERSION | ADDRV2_FORMAT);
DeserializeFileDB(anchors_db_path, WithParams(CAddress::V2_DISK, anchors));
LogPrintf("Loaded %i addresses from %s\n", anchors.size(), fs::quoted(fs::PathToString(anchors_db_path.filename())));
} catch (const std::exception&) {
anchors.clear();
Expand Down
7 changes: 4 additions & 3 deletions src/addrdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@
class ArgsManager;
class AddrMan;
class CAddress;
class CDataStream;
class DataStream;
class NetGroupManager;
struct bilingual_str;

bool DumpPeerAddresses(const ArgsManager& args, const AddrMan& addr);
/** Only used by tests. */
void ReadFromStream(AddrMan& addr, CDataStream& ssPeers);
void ReadFromStream(AddrMan& addr, DataStream& ssPeers);

bool DumpPeerAddresses(const ArgsManager& args, const AddrMan& addr);

/** Access to the banlist database (banlist.json) */
class CBanDB
Expand Down
25 changes: 9 additions & 16 deletions src/addrman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,7 @@ void AddrManImpl::Serialize(Stream& s_) const
*/

// Always serialize in the latest version (FILE_FORMAT).

OverrideStream<Stream> s(&s_, s_.GetType(), s_.GetVersion() | ADDRV2_FORMAT);
ParamsStream s{CAddress::V2_DISK, s_};

s << static_cast<uint8_t>(FILE_FORMAT);

Expand Down Expand Up @@ -236,14 +235,8 @@ void AddrManImpl::Unserialize(Stream& s_)
Format format;
s_ >> Using<CustomUintFormatter<1>>(format);

int stream_version = s_.GetVersion();
if (format >= Format::V3_BIP155) {
// Add ADDRV2_FORMAT to the version so that the CNetAddr and CAddress
// unserialize methods know that an address in addrv2 format is coming.
stream_version |= ADDRV2_FORMAT;
}

OverrideStream<Stream> s(&s_, s_.GetType(), stream_version);
const auto ser_params = (format >= Format::V3_BIP155 ? CAddress::V2_DISK : CAddress::V1_DISK);
ParamsStream s{ser_params, s_};

uint8_t compat;
s >> compat;
Expand Down Expand Up @@ -1273,12 +1266,12 @@ void AddrMan::Unserialize(Stream& s_)
}

// explicit instantiation
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);
template void AddrMan::Unserialize(CDataStream& s);
template void AddrMan::Unserialize(CHashVerifier<CDataStream>& s);
template void AddrMan::Serialize(HashedSourceWriter<AutoFile>&) const;
template void AddrMan::Serialize(DataStream&) const;
template void AddrMan::Unserialize(AutoFile&);
template void AddrMan::Unserialize(HashVerifier<AutoFile>&);
template void AddrMan::Unserialize(DataStream&);
template void AddrMan::Unserialize(HashVerifier<DataStream>&);

size_t AddrMan::Size(std::optional<Network> net, std::optional<bool> in_new) const
{
Expand Down
3 changes: 1 addition & 2 deletions src/addrman_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,7 @@ class AddrInfo : public CAddress

SERIALIZE_METHODS(AddrInfo, obj)
{
READWRITEAS(CAddress, obj);
READWRITE(obj.source, Using<ChronoFormatter<int64_t>>(obj.m_last_success), obj.nAttempts);
READWRITE(AsBase<CAddress>(obj), obj.source, Using<ChronoFormatter<int64_t>>(obj.m_last_success), obj.nAttempts);
}

AddrInfo(const CAddress &addrIn, const CNetAddr &addrSource) : CAddress(addrIn), source(addrSource)
Expand Down
41 changes: 3 additions & 38 deletions src/hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,55 +167,20 @@ class CHashWriter : public HashWriter
}
};

/** Reads data from an underlying stream, while hashing the read data. */
template<typename Source>
class CHashVerifier : public CHashWriter
{
private:
Source* source;

public:
explicit CHashVerifier(Source* source_) : CHashWriter(source_->GetType(), source_->GetVersion()), source(source_) {}

void read(Span<std::byte> dst)
{
source->read(dst);
this->write(dst);
}

void ignore(size_t nSize)
{
std::byte data[1024];
while (nSize > 0) {
size_t now = std::min<size_t>(nSize, 1024);
read({data, now});
nSize -= now;
}
}

template<typename T>
CHashVerifier<Source>& operator>>(T&& obj)
{
// Unserialize from this stream
::Unserialize(*this, obj);
return (*this);
}
};

/** Writes data to an underlying source stream, while hashing the written data. */
template <typename Source>
class HashedSourceWriter : public CHashWriter
class HashedSourceWriter : public HashWriter
{
private:
Source& m_source;

public:
explicit HashedSourceWriter(Source& source LIFETIMEBOUND) : CHashWriter{source.GetType(), source.GetVersion()}, m_source{source} {}
explicit HashedSourceWriter(Source& source LIFETIMEBOUND) : HashWriter{}, m_source{source} {}

void write(Span<const std::byte> src)
{
m_source.write(src);
CHashWriter::write(src);
HashWriter::write(src);
}

template <typename T>
Expand Down
3 changes: 1 addition & 2 deletions src/index/disktxpos.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ struct CDiskTxPos : public FlatFilePos

SERIALIZE_METHODS(CDiskTxPos, obj)
{
READWRITEAS(FlatFilePos, obj);
READWRITE(VARINT(obj.nTxOffset));
READWRITE(AsBase<FlatFilePos>(obj), VARINT(obj.nTxOffset));
}

CDiskTxPos(const FlatFilePos &blockIn, unsigned int nTxOffsetIn) : FlatFilePos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn) {
Expand Down
3 changes: 2 additions & 1 deletion src/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,8 @@ static std::vector<CAddress> ConvertSeeds(const std::vector<uint8_t> &vSeedsIn)
const auto one_week{7 * 24h};
std::vector<CAddress> vSeedsOut;
FastRandomContext rng;
CDataStream s(vSeedsIn, SER_NETWORK, PROTOCOL_VERSION | ADDRV2_FORMAT);
DataStream underlying_stream{vSeedsIn};
ParamsStream s{CAddress::V2_NETWORK, underlying_stream};
while (!s.eof()) {
CService endpoint;
s >> endpoint;
Expand Down
28 changes: 14 additions & 14 deletions src/net_processing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1534,8 +1534,8 @@ void PeerManagerImpl::PushNodeVersion(CNode& pnode, const Peer& peer)

const bool tx_relay{!RejectIncomingTxs(pnode)};
m_connman.PushMessage(&pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::VERSION, nProtocolVersion, my_services, nTime,
your_services, addr_you, // Together the pre-version-31402 serialization of CAddress "addrYou" (without nTime)
my_services, CService(), // Together the pre-version-31402 serialization of CAddress "addrMe" (without nTime)
your_services, WithParams(CNetAddr::V1, addr_you), // Together the pre-version-31402 serialization of CAddress "addrYou" (without nTime)
my_services, WithParams(CNetAddr::V1, CService{}), // Together the pre-version-31402 serialization of CAddress "addrMe" (without nTime)
nonce, strSubVersion, nNodeStartingHeight, tx_relay, mnauthChallenge, pnode.m_masternode_connection.load()));

if (fLogIPs) {
Expand Down Expand Up @@ -3771,7 +3771,7 @@ void PeerManagerImpl::ProcessMessage(
nTime = 0;
}
vRecv.ignore(8); // Ignore the addrMe service bits sent by the peer
vRecv >> addrMe;
vRecv >> WithParams(CNetAddr::V1, addrMe);
if (!pfrom.IsInboundConn())
{
// Overwrites potentially existing services. In contrast to this,
Expand Down Expand Up @@ -4189,17 +4189,17 @@ void PeerManagerImpl::ProcessMessage(
}

if (msg_type == NetMsgType::ADDR || msg_type == NetMsgType::ADDRV2) {
int stream_version = vRecv.GetVersion();
if (msg_type == NetMsgType::ADDRV2) {
// Add ADDRV2_FORMAT to the version so that the CNetAddr and CAddress
const auto ser_params{
msg_type == NetMsgType::ADDRV2 ?
// Set V2 param so that the CNetAddr and CAddress
// unserialize methods know that an address in v2 format is coming.
stream_version |= ADDRV2_FORMAT;
}
CAddress::V2_NETWORK :
CAddress::V1_NETWORK,
};

OverrideStream<CDataStream> s(&vRecv, vRecv.GetType(), stream_version);
std::vector<CAddress> vAddr;

s >> vAddr;
vRecv >> WithParams(ser_params, vAddr);

if (!SetupAddressRelay(pfrom, *peer)) {
LogPrint(BCLog::NET, "ignoring %s message from %s peer=%d\n", msg_type, pfrom.ConnectionTypeAsString(), pfrom.GetId());
Expand Down Expand Up @@ -5946,15 +5946,15 @@ void PeerManagerImpl::MaybeSendAddr(CNode& node, Peer& peer, std::chrono::micros
if (peer.m_addrs_to_send.empty()) return;

const char* msg_type;
int make_flags;
CNetAddr::Encoding ser_enc;
if (peer.m_wants_addrv2) {
msg_type = NetMsgType::ADDRV2;
make_flags = ADDRV2_FORMAT;
ser_enc = CNetAddr::Encoding::V2;
} else {
msg_type = NetMsgType::ADDR;
make_flags = 0;
ser_enc = CNetAddr::Encoding::V1;
}
m_connman.PushMessage(&node, CNetMsgMaker(node.GetCommonVersion()).Make(make_flags, msg_type, peer.m_addrs_to_send));
m_connman.PushMessage(&node, CNetMsgMaker(node.GetCommonVersion()).Make(msg_type, WithParams(CAddress::SerParams{{ser_enc}, CAddress::Format::Network}, peer.m_addrs_to_send)));
peer.m_addrs_to_send.clear();

// we only send the big addr message once
Expand Down
24 changes: 13 additions & 11 deletions src/netaddress.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,6 @@

extern bool fAllowPrivateNet;

/**
* A flag that is ORed into the protocol version to designate that addresses
* should be serialized in (unserialized from) v2 format (BIP155).
* Make sure that this does not collide with any of the values in `version.h`
*/
static constexpr int ADDRV2_FORMAT = 0x20000000;

/**
* A network type.
* @note An address may belong to more than one network, for example `10.0.0.1`
Expand Down Expand Up @@ -240,13 +233,23 @@ class CNetAddr
return IsIPv4() || IsIPv6() || IsTor() || IsI2P() || IsCJDNS();
}

enum class Encoding {
V1,
V2, //!< BIP155 encoding
};
struct SerParams {
const Encoding enc;
};
static constexpr SerParams V1{Encoding::V1};
static constexpr SerParams V2{Encoding::V2};

/**
* Serialize to a stream.
*/
template <typename Stream>
void Serialize(Stream& s) const
{
if (s.GetVersion() & ADDRV2_FORMAT) {
if (s.GetParams().enc == Encoding::V2) {
SerializeV2Stream(s);
} else {
SerializeV1Stream(s);
Expand All @@ -259,7 +262,7 @@ class CNetAddr
template <typename Stream>
void Unserialize(Stream& s)
{
if (s.GetVersion() & ADDRV2_FORMAT) {
if (s.GetParams().enc == Encoding::V2) {
UnserializeV2Stream(s);
} else {
UnserializeV1Stream(s);
Expand Down Expand Up @@ -566,8 +569,7 @@ class CService : public CNetAddr

SERIALIZE_METHODS(CService, obj)
{
READWRITEAS(CNetAddr, obj);
READWRITE(Using<BigEndianFormatter<2>>(obj.port));
READWRITE(AsBase<CNetAddr>(obj), Using<BigEndianFormatter<2>>(obj.port));
}

friend class CServiceHash;
Expand Down
3 changes: 1 addition & 2 deletions src/primitives/block.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,7 @@ class CBlock : public CBlockHeader

SERIALIZE_METHODS(CBlock, obj)
{
READWRITEAS(CBlockHeader, obj);
READWRITE(obj.vtx);
READWRITE(AsBase<CBlockHeader>(obj), obj.vtx);
}

void SetNull()
Expand Down
Loading
Loading