Skip to content

Commit 1622543

Browse files
[addrman] Move CAddrMan::Serialize to cpp file
Reviewer hint: use `git diff --color-moved=dimmed-zebra --color-moved-ws=ignore-all-space` Co-authored-by: Amiti Uttarwar <[email protected]>
1 parent 4fc15d1 commit 1622543

File tree

2 files changed

+109
-101
lines changed

2 files changed

+109
-101
lines changed

src/addrman.cpp

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,114 @@ CAddrMan::CAddrMan(bool deterministic, int32_t consistency_check_ratio)
9494
}
9595
}
9696

97+
template <typename Stream>
98+
void CAddrMan::Serialize(Stream& s_) const
99+
{
100+
LOCK(cs);
101+
102+
/**
103+
* Serialized format.
104+
* * format version byte (@see `Format`)
105+
* * lowest compatible format version byte. This is used to help old software decide
106+
* whether to parse the file. For example:
107+
* * Bitcoin Core version N knows how to parse up to format=3. If a new format=4 is
108+
* introduced in version N+1 that is compatible with format=3 and it is known that
109+
* version N will be able to parse it, then version N+1 will write
110+
* (format=4, lowest_compatible=3) in the first two bytes of the file, and so
111+
* version N will still try to parse it.
112+
* * Bitcoin Core version N+2 introduces a new incompatible format=5. It will write
113+
* (format=5, lowest_compatible=5) and so any versions that do not know how to parse
114+
* format=5 will not try to read the file.
115+
* * nKey
116+
* * nNew
117+
* * nTried
118+
* * number of "new" buckets XOR 2**30
119+
* * all new addresses (total count: nNew)
120+
* * all tried addresses (total count: nTried)
121+
* * for each new bucket:
122+
* * number of elements
123+
* * for each element: index in the serialized "all new addresses"
124+
* * asmap checksum
125+
*
126+
* 2**30 is xorred with the number of buckets to make addrman deserializer v0 detect it
127+
* as incompatible. This is necessary because it did not check the version number on
128+
* deserialization.
129+
*
130+
* vvNew, vvTried, mapInfo, mapAddr and vRandom are never encoded explicitly;
131+
* they are instead reconstructed from the other information.
132+
*
133+
* This format is more complex, but significantly smaller (at most 1.5 MiB), and supports
134+
* changes to the ADDRMAN_ parameters without breaking the on-disk structure.
135+
*
136+
* We don't use SERIALIZE_METHODS since the serialization and deserialization code has
137+
* very little in common.
138+
*/
139+
140+
// Always serialize in the latest version (FILE_FORMAT).
141+
142+
OverrideStream<Stream> s(&s_, s_.GetType(), s_.GetVersion() | ADDRV2_FORMAT);
143+
144+
s << static_cast<uint8_t>(FILE_FORMAT);
145+
146+
// Increment `lowest_compatible` iff a newly introduced format is incompatible with
147+
// the previous one.
148+
static constexpr uint8_t lowest_compatible = Format::V3_BIP155;
149+
s << static_cast<uint8_t>(INCOMPATIBILITY_BASE + lowest_compatible);
150+
151+
s << nKey;
152+
s << nNew;
153+
s << nTried;
154+
155+
int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30);
156+
s << nUBuckets;
157+
std::unordered_map<int, int> mapUnkIds;
158+
int nIds = 0;
159+
for (const auto& entry : mapInfo) {
160+
mapUnkIds[entry.first] = nIds;
161+
const CAddrInfo &info = entry.second;
162+
if (info.nRefCount) {
163+
assert(nIds != nNew); // this means nNew was wrong, oh ow
164+
s << info;
165+
nIds++;
166+
}
167+
}
168+
nIds = 0;
169+
for (const auto& entry : mapInfo) {
170+
const CAddrInfo &info = entry.second;
171+
if (info.fInTried) {
172+
assert(nIds != nTried); // this means nTried was wrong, oh ow
173+
s << info;
174+
nIds++;
175+
}
176+
}
177+
for (int bucket = 0; bucket < ADDRMAN_NEW_BUCKET_COUNT; bucket++) {
178+
int nSize = 0;
179+
for (int i = 0; i < ADDRMAN_BUCKET_SIZE; i++) {
180+
if (vvNew[bucket][i] != -1)
181+
nSize++;
182+
}
183+
s << nSize;
184+
for (int i = 0; i < ADDRMAN_BUCKET_SIZE; i++) {
185+
if (vvNew[bucket][i] != -1) {
186+
int nIndex = mapUnkIds[vvNew[bucket][i]];
187+
s << nIndex;
188+
}
189+
}
190+
}
191+
// Store asmap checksum after bucket entries so that it
192+
// can be ignored by older clients for backward compatibility.
193+
uint256 asmap_checksum;
194+
if (m_asmap.size() != 0) {
195+
asmap_checksum = SerializeHash(m_asmap);
196+
}
197+
s << asmap_checksum;
198+
}
199+
200+
// explicit instantiation
201+
template void CAddrMan::Serialize(CHashWriter& s) const;
202+
template void CAddrMan::Serialize(CAutoFile& s) const;
203+
template void CAddrMan::Serialize(CDataStream& s) const;
204+
97205
CAddrInfo* CAddrMan::Find(const CNetAddr& addr, int* pnId)
98206
{
99207
AssertLockHeld(cs);

src/addrman.h

Lines changed: 1 addition & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -200,108 +200,8 @@ class CAddrMan
200200
// Read asmap from provided binary file
201201
static std::vector<bool> DecodeAsmap(fs::path path);
202202

203-
/**
204-
* Serialized format.
205-
* * format version byte (@see `Format`)
206-
* * lowest compatible format version byte. This is used to help old software decide
207-
* whether to parse the file. For example:
208-
* * Bitcoin Core version N knows how to parse up to format=3. If a new format=4 is
209-
* introduced in version N+1 that is compatible with format=3 and it is known that
210-
* version N will be able to parse it, then version N+1 will write
211-
* (format=4, lowest_compatible=3) in the first two bytes of the file, and so
212-
* version N will still try to parse it.
213-
* * Bitcoin Core version N+2 introduces a new incompatible format=5. It will write
214-
* (format=5, lowest_compatible=5) and so any versions that do not know how to parse
215-
* format=5 will not try to read the file.
216-
* * nKey
217-
* * nNew
218-
* * nTried
219-
* * number of "new" buckets XOR 2**30
220-
* * all new addresses (total count: nNew)
221-
* * all tried addresses (total count: nTried)
222-
* * for each new bucket:
223-
* * number of elements
224-
* * for each element: index in the serialized "all new addresses"
225-
* * asmap checksum
226-
*
227-
* 2**30 is xorred with the number of buckets to make addrman deserializer v0 detect it
228-
* as incompatible. This is necessary because it did not check the version number on
229-
* deserialization.
230-
*
231-
* vvNew, vvTried, mapInfo, mapAddr and vRandom are never encoded explicitly;
232-
* they are instead reconstructed from the other information.
233-
*
234-
* This format is more complex, but significantly smaller (at most 1.5 MiB), and supports
235-
* changes to the ADDRMAN_ parameters without breaking the on-disk structure.
236-
*
237-
* We don't use SERIALIZE_METHODS since the serialization and deserialization code has
238-
* very little in common.
239-
*/
240203
template <typename Stream>
241-
void Serialize(Stream& s_) const
242-
EXCLUSIVE_LOCKS_REQUIRED(!cs)
243-
{
244-
LOCK(cs);
245-
246-
// Always serialize in the latest version (FILE_FORMAT).
247-
248-
OverrideStream<Stream> s(&s_, s_.GetType(), s_.GetVersion() | ADDRV2_FORMAT);
249-
250-
s << static_cast<uint8_t>(FILE_FORMAT);
251-
252-
// Increment `lowest_compatible` iff a newly introduced format is incompatible with
253-
// the previous one.
254-
static constexpr uint8_t lowest_compatible = Format::V3_BIP155;
255-
s << static_cast<uint8_t>(INCOMPATIBILITY_BASE + lowest_compatible);
256-
257-
s << nKey;
258-
s << nNew;
259-
s << nTried;
260-
261-
int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30);
262-
s << nUBuckets;
263-
std::unordered_map<int, int> mapUnkIds;
264-
int nIds = 0;
265-
for (const auto& entry : mapInfo) {
266-
mapUnkIds[entry.first] = nIds;
267-
const CAddrInfo &info = entry.second;
268-
if (info.nRefCount) {
269-
assert(nIds != nNew); // this means nNew was wrong, oh ow
270-
s << info;
271-
nIds++;
272-
}
273-
}
274-
nIds = 0;
275-
for (const auto& entry : mapInfo) {
276-
const CAddrInfo &info = entry.second;
277-
if (info.fInTried) {
278-
assert(nIds != nTried); // this means nTried was wrong, oh ow
279-
s << info;
280-
nIds++;
281-
}
282-
}
283-
for (int bucket = 0; bucket < ADDRMAN_NEW_BUCKET_COUNT; bucket++) {
284-
int nSize = 0;
285-
for (int i = 0; i < ADDRMAN_BUCKET_SIZE; i++) {
286-
if (vvNew[bucket][i] != -1)
287-
nSize++;
288-
}
289-
s << nSize;
290-
for (int i = 0; i < ADDRMAN_BUCKET_SIZE; i++) {
291-
if (vvNew[bucket][i] != -1) {
292-
int nIndex = mapUnkIds[vvNew[bucket][i]];
293-
s << nIndex;
294-
}
295-
}
296-
}
297-
// Store asmap checksum after bucket entries so that it
298-
// can be ignored by older clients for backward compatibility.
299-
uint256 asmap_checksum;
300-
if (m_asmap.size() != 0) {
301-
asmap_checksum = SerializeHash(m_asmap);
302-
}
303-
s << asmap_checksum;
304-
}
204+
void Serialize(Stream& s_) const EXCLUSIVE_LOCKS_REQUIRED(!cs);
305205

306206
template <typename Stream>
307207
void Unserialize(Stream& s_)

0 commit comments

Comments
 (0)