@@ -94,6 +94,114 @@ CAddrMan::CAddrMan(bool deterministic, int32_t consistency_check_ratio)
94
94
}
95
95
}
96
96
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
+
97
205
CAddrInfo* CAddrMan::Find (const CNetAddr& addr, int * pnId)
98
206
{
99
207
AssertLockHeld (cs);
0 commit comments