-
Notifications
You must be signed in to change notification settings - Fork 36.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Well-defined CAddress disk serialization, and addrv2 anchors.dat #20516
Conversation
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
94fdec1
to
1991447
Compare
1991447
to
04e3733
Compare
I merged the anchors.dat addrv2 support from #20514 into this PR, as doing it correctly requires changes the |
Concept ACK. From the PR description and quick code reading it follows that there is no hurry to backport these changes into 0.21, right? |
Indeed, there is probably no hurry, unless we want to support torv3 anchors in 0.21. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In commit 6d16903 message:
These do no introduce incompatibilities, as no code versions exist that write
any value other than 0 or 0x20000000 in the top 19 bits, and no code paths
where the stream's version differs from the stored version.
s/top 19/high 13/ ?
22b8c55
to
80f5c54
Compare
Addressed comments. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approach ACK 80f5c54
Before this commit, CAddress disk serialization was messy. It stored CLIENT_VERSION in the first 4 bytes, optionally OR'ed with ADDRV2_FORMAT. - All bits except ADDRV2_FORMAT were ignored, making it hard to use for actual future format changes. - ADDRV2_FORMAT determines whether or not nServices is serialized in LE64 format or in CompactSize format. - Whether or not the embedded CService is serialized in V1 or V2 format is determined by the stream's version having ADDRV2_FORMAT (as opposed to the nServices encoding, which is determined by the disk version). To improve the situation, this commit introduces the following disk serialization format, compatible with earlier versions, but better defined for future changes: - The first 4 bytes store a format version number. Its low 19 bits are ignored (as it historically stored the CLIENT_VERSION), but its high 13 bits specify the serialization exactly: - 0x00000000: LE64 encoding for nServices, V1 encoding for CService - 0x20000000: CompactSize encoding for nServices, V2 encoding for CService - Any other value triggers an unsupported format error on deserialization, and can be used for future format changes. - The ADDRV2_FORMAT flag in the stream's version does not impact the actual serialization format; it only determines whether V2 encoding is permitted; whether it's actually enabled depends solely on the disk version number. Operationally the changes to the deserializer are: - Failure when the stored format version number is unexpected. - The embedded CService's format is determined by the stored format version number rather than the stream's version number. These do no introduce incompatibilities, as no code versions exist that write any value other than 0 or 0x20000000 in the top 13 bits, and no code paths where the stream's version differs from the stored version.
Rebased, and addressed comments. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK f8866e8
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK f8866e8 tested rebased to master and built/run/restarted with DEBUG_ADDRMAN, peers.dat and anchors ser/deser seems fine
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approach ACK
@hebasto I think you need to leave a new review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
uint32_t stored_format_version = DISK_VERSION_INIT; | ||
if (s.GetVersion() & ADDRV2_FORMAT) stored_format_version |= DISK_VERSION_ADDRV2; | ||
READWRITE(stored_format_version); | ||
stored_format_version &= ~DISK_VERSION_IGNORE_MASK; // ignore low bits |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
This is the only place (besides two assertions above) where DISK_VERSION_IGNORE_MASK
is used, and it is inverted. Isn't it more clear:
stored_format_version &= ~DISK_VERSION_IGNORE_MASK; // ignore low bits | |
stored_format_version &= DISK_VERSION_MASK; // ignore low bits |
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do if I retouch.
ACK f8866e8 |
Code review ACK f8866e8 |
…drv2 anchors.dat f8866e8 Add roundtrip fuzz tests for CAddress serialization (Pieter Wuille) e2f0548 Use addrv2 serialization in anchors.dat (Pieter Wuille) 8cd8f37 Introduce well-defined CAddress disk serialization (Pieter Wuille) Pull request description: Alternative to bitcoin#20509. This makes the `CAddress` disk serialization format well defined, and uses it to enable addrv2 support in anchors.dat (in a way that's compatible with older software). The new format is: - The first 4 bytes store a format version number. Its low 19 bits are ignored (as those historically stored the `CLIENT_VERSION`), but its high 13 bits specify the actual serialization: - 0x00000000: LE64 encoding for `nServices`, V1 encoding for `CService` (like pre-BIP155 network serialization). - 0x20000000: CompactSize encoding for `nServices`, V2 encoding for `CService` (like BIP155 network serialization). - Any other value triggers an unsupported format error on deserialization, and can be used for future format changes. - The `ADDRV2_FORMAT` flag in the stream's version does not determine the actual serialization format; it only sets whether or not V2 encoding is permitted. ACKs for top commit: achow101: ACK f8866e8 laanwj: Code review ACK f8866e8 vasild: ACK f8866e8 jonatack: ACK f8866e8 tested rebased to master and built/run/restarted with DEBUG_ADDRMAN, peers.dat and anchors ser/deser seems fine hebasto: ACK f8866e8, tested on Linux Mint 20.1 (x86_64). Tree-SHA512: 3898f8a8c51783a46dd0aae03fa10060521f5dd6e79315fe95ba807689e78f202388ffa28c40bf156c6f7b1fc2ce806b155dcbe56027df73d039a55331723796
review ACK f8866e8 🕑 Show signature and timestampSignature:
Timestamp of file with hash |
@@ -251,9 +251,37 @@ FUZZ_TARGET_DESERIALIZE(messageheader_deserialize, { | |||
DeserializeFromFuzzingInput(buffer, mh); | |||
(void)mh.IsCommandValid(); | |||
}) | |||
FUZZ_TARGET_DESERIALIZE(address_deserialize, { | |||
FUZZ_TARGET_DESERIALIZE(address_deserialize_v1_notime, { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copied the fuzz inputs in commit bitcoin-core/qa-assets@836513a, so that the targets have something nice to start with.
Alternative to #20509.
This makes the
CAddress
disk serialization format well defined, and uses it to enable addrv2 support in anchors.dat (in a way that's compatible with older software). The new format is:CLIENT_VERSION
), but its high 13 bits specify the actual serialization:nServices
, V1 encoding forCService
(like pre-BIP155 network serialization).nServices
, V2 encoding forCService
(like BIP155 network serialization).ADDRV2_FORMAT
flag in the stream's version does not determine the actual serialization format; it only sets whether or not V2 encoding is permitted.