Skip to content

Commit 8e0d979

Browse files
committed
Merge bitcoin/bitcoin#25284: net: Use serialization parameters for CAddress serialization
fa626af Remove unused legacy CHashVerifier (MarcoFalke) fafa3fc test: add tests that exercise WithParams() (MarcoFalke) fac81af Use serialization parameters for CAddress serialization (MarcoFalke) faec591 Support for serialization parameters (MarcoFalke) fac42e9 Rename CSerAction* to Action* (MarcoFalke) aaaa3fa Replace READWRITEAS macro with AsBase wrapping function (MarcoFalke) Pull request description: It seems confusing that picking a wrong value for `ADDRV2_FORMAT` could have effects on consensus. (See the docstring of `ADDRV2_FORMAT`). Fix this by implementing bitcoin/bitcoin#19477 (comment) . This may also help with libbitcoinkernel, see bitcoin/bitcoin#28327 ACKs for top commit: TheCharlatan: ACK fa626af ajtowns: ACK fa626af Tree-SHA512: 229d379da27308890de212b1fd2b85dac13f3f768413cb56a4b0c2da708f28344d04356ffd75bfcbaa4cabf0b6cc363c4f812a8f1648cff9e436811498278318
2 parents 5ad4eb3 + fa626af commit 8e0d979

26 files changed

+594
-297
lines changed

src/addrdb.cpp

+12-13
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,16 @@ bool SerializeDB(Stream& stream, const Data& data)
4747
}
4848

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

56-
// open temp output file, and associate with CAutoFile
56+
// open temp output file
5757
fs::path pathTmp = gArgs.GetDataDirNet() / fs::u8path(tmpfn);
5858
FILE *file = fsbridge::fopen(pathTmp, "wb");
59-
CAutoFile fileout(file, SER_DISK, version);
59+
AutoFile fileout{file};
6060
if (fileout.IsNull()) {
6161
fileout.fclose();
6262
remove(pathTmp);
@@ -86,9 +86,9 @@ bool SerializeFileDB(const std::string& prefix, const fs::path& path, const Data
8686
}
8787

8888
template <typename Stream, typename Data>
89-
void DeserializeDB(Stream& stream, Data& data, bool fCheckSum = true)
89+
void DeserializeDB(Stream& stream, Data&& data, bool fCheckSum = true)
9090
{
91-
CHashVerifier<Stream> verifier(&stream);
91+
HashVerifier verifier{stream};
9292
// de-serialize file header (network specific magic number) and ..
9393
unsigned char pchMsgTmp[4];
9494
verifier >> pchMsgTmp;
@@ -111,11 +111,10 @@ void DeserializeDB(Stream& stream, Data& data, bool fCheckSum = true)
111111
}
112112

113113
template <typename Data>
114-
void DeserializeFileDB(const fs::path& path, Data& data, int version)
114+
void DeserializeFileDB(const fs::path& path, Data&& data)
115115
{
116-
// open input file, and associate with CAutoFile
117116
FILE* file = fsbridge::fopen(path, "rb");
118-
CAutoFile filein(file, SER_DISK, version);
117+
AutoFile filein{file};
119118
if (filein.IsNull()) {
120119
throw DbNotFoundError{};
121120
}
@@ -175,10 +174,10 @@ bool CBanDB::Read(banmap_t& banSet)
175174
bool DumpPeerAddresses(const ArgsManager& args, const AddrMan& addr)
176175
{
177176
const auto pathAddr = args.GetDataDirNet() / "peers.dat";
178-
return SerializeFileDB("peers", pathAddr, addr, CLIENT_VERSION);
177+
return SerializeFileDB("peers", pathAddr, addr);
179178
}
180179

181-
void ReadFromStream(AddrMan& addr, CDataStream& ssPeers)
180+
void ReadFromStream(AddrMan& addr, DataStream& ssPeers)
182181
{
183182
DeserializeDB(ssPeers, addr, false);
184183
}
@@ -191,7 +190,7 @@ util::Result<std::unique_ptr<AddrMan>> LoadAddrman(const NetGroupManager& netgro
191190
const auto start{SteadyClock::now()};
192191
const auto path_addr{args.GetDataDirNet() / "peers.dat"};
193192
try {
194-
DeserializeFileDB(path_addr, *addrman, CLIENT_VERSION);
193+
DeserializeFileDB(path_addr, *addrman);
195194
LogPrintf("Loaded %i addresses from peers.dat %dms\n", addrman->Size(), Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
196195
} catch (const DbNotFoundError&) {
197196
// Addrman can be in an inconsistent state after failure, reset it
@@ -217,14 +216,14 @@ util::Result<std::unique_ptr<AddrMan>> LoadAddrman(const NetGroupManager& netgro
217216
void DumpAnchors(const fs::path& anchors_db_path, const std::vector<CAddress>& anchors)
218217
{
219218
LOG_TIME_SECONDS(strprintf("Flush %d outbound block-relay-only peer addresses to anchors.dat", anchors.size()));
220-
SerializeFileDB("anchors", anchors_db_path, anchors, CLIENT_VERSION | ADDRV2_FORMAT);
219+
SerializeFileDB("anchors", anchors_db_path, WithParams(CAddress::V2_DISK, anchors));
221220
}
222221

223222
std::vector<CAddress> ReadAnchors(const fs::path& anchors_db_path)
224223
{
225224
std::vector<CAddress> anchors;
226225
try {
227-
DeserializeFileDB(anchors_db_path, anchors, CLIENT_VERSION | ADDRV2_FORMAT);
226+
DeserializeFileDB(anchors_db_path, WithParams(CAddress::V2_DISK, anchors));
228227
LogPrintf("Loaded %i addresses from %s\n", anchors.size(), fs::quoted(fs::PathToString(anchors_db_path.filename())));
229228
} catch (const std::exception&) {
230229
anchors.clear();

src/addrdb.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@
1616
class ArgsManager;
1717
class AddrMan;
1818
class CAddress;
19-
class CDataStream;
19+
class DataStream;
2020
class NetGroupManager;
2121

22-
bool DumpPeerAddresses(const ArgsManager& args, const AddrMan& addr);
2322
/** Only used by tests. */
24-
void ReadFromStream(AddrMan& addr, CDataStream& ssPeers);
23+
void ReadFromStream(AddrMan& addr, DataStream& ssPeers);
24+
25+
bool DumpPeerAddresses(const ArgsManager& args, const AddrMan& addr);
2526

2627
/** Access to the banlist database (banlist.json) */
2728
class CBanDB

src/addrman.cpp

+9-16
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,7 @@ void AddrManImpl::Serialize(Stream& s_) const
171171
*/
172172

173173
// Always serialize in the latest version (FILE_FORMAT).
174-
175-
OverrideStream<Stream> s(&s_, s_.GetType(), s_.GetVersion() | ADDRV2_FORMAT);
174+
ParamsStream s{CAddress::V2_DISK, s_};
176175

177176
s << static_cast<uint8_t>(FILE_FORMAT);
178177

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

239-
int stream_version = s_.GetVersion();
240-
if (format >= Format::V3_BIP155) {
241-
// Add ADDRV2_FORMAT to the version so that the CNetAddr and CAddress
242-
// unserialize methods know that an address in addrv2 format is coming.
243-
stream_version |= ADDRV2_FORMAT;
244-
}
245-
246-
OverrideStream<Stream> s(&s_, s_.GetType(), stream_version);
238+
const auto ser_params = (format >= Format::V3_BIP155 ? CAddress::V2_DISK : CAddress::V1_DISK);
239+
ParamsStream s{ser_params, s_};
247240

248241
uint8_t compat;
249242
s >> compat;
@@ -1249,12 +1242,12 @@ void AddrMan::Unserialize(Stream& s_)
12491242
}
12501243

12511244
// explicit instantiation
1252-
template void AddrMan::Serialize(HashedSourceWriter<CAutoFile>& s) const;
1253-
template void AddrMan::Serialize(CDataStream& s) const;
1254-
template void AddrMan::Unserialize(CAutoFile& s);
1255-
template void AddrMan::Unserialize(CHashVerifier<CAutoFile>& s);
1256-
template void AddrMan::Unserialize(CDataStream& s);
1257-
template void AddrMan::Unserialize(CHashVerifier<CDataStream>& s);
1245+
template void AddrMan::Serialize(HashedSourceWriter<AutoFile>&) const;
1246+
template void AddrMan::Serialize(DataStream&) const;
1247+
template void AddrMan::Unserialize(AutoFile&);
1248+
template void AddrMan::Unserialize(HashVerifier<AutoFile>&);
1249+
template void AddrMan::Unserialize(DataStream&);
1250+
template void AddrMan::Unserialize(HashVerifier<DataStream>&);
12581251

12591252
size_t AddrMan::Size(std::optional<Network> net, std::optional<bool> in_new) const
12601253
{

src/addrman_impl.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,7 @@ class AddrInfo : public CAddress
6565

6666
SERIALIZE_METHODS(AddrInfo, obj)
6767
{
68-
READWRITEAS(CAddress, obj);
69-
READWRITE(obj.source, Using<ChronoFormatter<int64_t>>(obj.m_last_success), obj.nAttempts);
68+
READWRITE(AsBase<CAddress>(obj), obj.source, Using<ChronoFormatter<int64_t>>(obj.m_last_success), obj.nAttempts);
7069
}
7170

7271
AddrInfo(const CAddress &addrIn, const CNetAddr &addrSource) : CAddress(addrIn), source(addrSource)

src/hash.h

+3-36
Original file line numberDiff line numberDiff line change
@@ -199,53 +199,20 @@ class HashVerifier : public HashWriter
199199
}
200200
};
201201

202-
template<typename Source>
203-
class CHashVerifier : public CHashWriter
204-
{
205-
private:
206-
Source* source;
207-
208-
public:
209-
explicit CHashVerifier(Source* source_) : CHashWriter(source_->GetType(), source_->GetVersion()), source(source_) {}
210-
211-
void read(Span<std::byte> dst)
212-
{
213-
source->read(dst);
214-
this->write(dst);
215-
}
216-
217-
void ignore(size_t nSize)
218-
{
219-
std::byte data[1024];
220-
while (nSize > 0) {
221-
size_t now = std::min<size_t>(nSize, 1024);
222-
read({data, now});
223-
nSize -= now;
224-
}
225-
}
226-
227-
template<typename T>
228-
CHashVerifier<Source>& operator>>(T&& obj)
229-
{
230-
::Unserialize(*this, obj);
231-
return (*this);
232-
}
233-
};
234-
235202
/** Writes data to an underlying source stream, while hashing the written data. */
236203
template <typename Source>
237-
class HashedSourceWriter : public CHashWriter
204+
class HashedSourceWriter : public HashWriter
238205
{
239206
private:
240207
Source& m_source;
241208

242209
public:
243-
explicit HashedSourceWriter(Source& source LIFETIMEBOUND) : CHashWriter{source.GetType(), source.GetVersion()}, m_source{source} {}
210+
explicit HashedSourceWriter(Source& source LIFETIMEBOUND) : HashWriter{}, m_source{source} {}
244211

245212
void write(Span<const std::byte> src)
246213
{
247214
m_source.write(src);
248-
CHashWriter::write(src);
215+
HashWriter::write(src);
249216
}
250217

251218
template <typename T>

src/index/disktxpos.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ struct CDiskTxPos : public FlatFilePos
1414

1515
SERIALIZE_METHODS(CDiskTxPos, obj)
1616
{
17-
READWRITEAS(FlatFilePos, obj);
18-
READWRITE(VARINT(obj.nTxOffset));
17+
READWRITE(AsBase<FlatFilePos>(obj), VARINT(obj.nTxOffset));
1918
}
2019

2120
CDiskTxPos(const FlatFilePos &blockIn, unsigned int nTxOffsetIn) : FlatFilePos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn) {

src/net.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,8 @@ static std::vector<CAddress> ConvertSeeds(const std::vector<uint8_t> &vSeedsIn)
202202
const auto one_week{7 * 24h};
203203
std::vector<CAddress> vSeedsOut;
204204
FastRandomContext rng;
205-
CDataStream s(vSeedsIn, SER_NETWORK, PROTOCOL_VERSION | ADDRV2_FORMAT);
205+
DataStream underlying_stream{vSeedsIn};
206+
ParamsStream s{CAddress::V2_NETWORK, underlying_stream};
206207
while (!s.eof()) {
207208
CService endpoint;
208209
s >> endpoint;

src/net_processing.cpp

+14-14
Original file line numberDiff line numberDiff line change
@@ -1415,8 +1415,8 @@ void PeerManagerImpl::PushNodeVersion(CNode& pnode, const Peer& peer)
14151415

14161416
const bool tx_relay{!RejectIncomingTxs(pnode)};
14171417
m_connman.PushMessage(&pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::VERSION, PROTOCOL_VERSION, my_services, nTime,
1418-
your_services, addr_you, // Together the pre-version-31402 serialization of CAddress "addrYou" (without nTime)
1419-
my_services, CService(), // Together the pre-version-31402 serialization of CAddress "addrMe" (without nTime)
1418+
your_services, WithParams(CNetAddr::V1, addr_you), // Together the pre-version-31402 serialization of CAddress "addrYou" (without nTime)
1419+
my_services, WithParams(CNetAddr::V1, CService{}), // Together the pre-version-31402 serialization of CAddress "addrMe" (without nTime)
14201420
nonce, strSubVersion, nNodeStartingHeight, tx_relay));
14211421

14221422
if (fLogIPs) {
@@ -3293,7 +3293,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
32933293
nTime = 0;
32943294
}
32953295
vRecv.ignore(8); // Ignore the addrMe service bits sent by the peer
3296-
vRecv >> addrMe;
3296+
vRecv >> WithParams(CNetAddr::V1, addrMe);
32973297
if (!pfrom.IsInboundConn())
32983298
{
32993299
m_addrman.SetServices(pfrom.addr, nServices);
@@ -3672,17 +3672,17 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
36723672
}
36733673

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

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

3685-
s >> vAddr;
3685+
vRecv >> WithParams(ser_params, vAddr);
36863686

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

52915291
const char* msg_type;
5292-
int make_flags;
5292+
CNetAddr::Encoding ser_enc;
52935293
if (peer.m_wants_addrv2) {
52945294
msg_type = NetMsgType::ADDRV2;
5295-
make_flags = ADDRV2_FORMAT;
5295+
ser_enc = CNetAddr::Encoding::V2;
52965296
} else {
52975297
msg_type = NetMsgType::ADDR;
5298-
make_flags = 0;
5298+
ser_enc = CNetAddr::Encoding::V1;
52995299
}
5300-
m_connman.PushMessage(&node, CNetMsgMaker(node.GetCommonVersion()).Make(make_flags, msg_type, peer.m_addrs_to_send));
5300+
m_connman.PushMessage(&node, CNetMsgMaker(node.GetCommonVersion()).Make(msg_type, WithParams(CAddress::SerParams{{ser_enc}, CAddress::Format::Network}, peer.m_addrs_to_send)));
53015301
peer.m_addrs_to_send.clear();
53025302

53035303
// we only send the big addr message once

src/netaddress.h

+13-12
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,6 @@
2424
#include <string>
2525
#include <vector>
2626

27-
/**
28-
* A flag that is ORed into the protocol version to designate that addresses
29-
* should be serialized in (unserialized from) v2 format (BIP155).
30-
* Make sure that this does not collide with any of the values in `version.h`
31-
* or with `SERIALIZE_TRANSACTION_NO_WITNESS`.
32-
*/
33-
static constexpr int ADDRV2_FORMAT = 0x20000000;
34-
3527
/**
3628
* A network type.
3729
* @note An address may belong to more than one network, for example `10.0.0.1`
@@ -220,13 +212,23 @@ class CNetAddr
220212
return IsIPv4() || IsIPv6() || IsTor() || IsI2P() || IsCJDNS();
221213
}
222214

215+
enum class Encoding {
216+
V1,
217+
V2, //!< BIP155 encoding
218+
};
219+
struct SerParams {
220+
const Encoding enc;
221+
};
222+
static constexpr SerParams V1{Encoding::V1};
223+
static constexpr SerParams V2{Encoding::V2};
224+
223225
/**
224226
* Serialize to a stream.
225227
*/
226228
template <typename Stream>
227229
void Serialize(Stream& s) const
228230
{
229-
if (s.GetVersion() & ADDRV2_FORMAT) {
231+
if (s.GetParams().enc == Encoding::V2) {
230232
SerializeV2Stream(s);
231233
} else {
232234
SerializeV1Stream(s);
@@ -239,7 +241,7 @@ class CNetAddr
239241
template <typename Stream>
240242
void Unserialize(Stream& s)
241243
{
242-
if (s.GetVersion() & ADDRV2_FORMAT) {
244+
if (s.GetParams().enc == Encoding::V2) {
243245
UnserializeV2Stream(s);
244246
} else {
245247
UnserializeV1Stream(s);
@@ -540,8 +542,7 @@ class CService : public CNetAddr
540542

541543
SERIALIZE_METHODS(CService, obj)
542544
{
543-
READWRITEAS(CNetAddr, obj);
544-
READWRITE(Using<BigEndianFormatter<2>>(obj.port));
545+
READWRITE(AsBase<CNetAddr>(obj), Using<BigEndianFormatter<2>>(obj.port));
545546
}
546547

547548
friend class CServiceHash;

src/primitives/block.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,7 @@ class CBlock : public CBlockHeader
8787

8888
SERIALIZE_METHODS(CBlock, obj)
8989
{
90-
READWRITEAS(CBlockHeader, obj);
91-
READWRITE(obj.vtx);
90+
READWRITE(AsBase<CBlockHeader>(obj), obj.vtx);
9291
}
9392

9493
void SetNull()

0 commit comments

Comments
 (0)