[v0.20.x-branch] Backport #10529: graphdb: fix backwards-compat for channel edge feature deserialization#10546
Conversation
|
Please cherry-pick the changes locally and resolve any conflicts. git fetch origin backport-10529-to-v0.20.x-branch
git worktree add --checkout .worktree/backport-10529-to-v0.20.x-branch backport-10529-to-v0.20.x-branch
cd .worktree/backport-10529-to-v0.20.x-branch
git reset --hard HEAD^
git cherry-pick -x 56a7f45b998054ad290ecfe3ede57f274b58a5b4
git push --force-with-lease |
This commit fixes a backwards compatibility issue that prevented nodes from upgrading from v0.19.x to v0.20.x. In v0.19.x, channel edge features were serialized as raw feature bytes without a length prefix. In v0.20.x (commit 2f2845d), the serialization changed to use Features.Encode() which adds a 2-byte big-endian length prefix before the feature bits. The deserialization code was updated to use Features.Decode() which expects this length prefix. When v0.20.x reads a database created by v0.19.x, Decode() tries to read a length prefix that doesn't exist, causing an EOF error: unable to decode features: EOF The fix adds a deserializeChanEdgeFeatures() helper that detects which format is being read and decodes accordingly: - New format (v0.20+): First 2 bytes encode the length of the remaining bytes. Detected when uint16(bytes[0:2]) == len(bytes)-2. - Legacy format (pre-v0.20): Raw feature bits without length prefix. Uses DecodeBase256 with the known length. The format detection is safe because in the legacy format, the first byte always has at least one bit set (the serialization uses minimum bytes), so the first two bytes can never encode a value equal to len-2. Fixes #10528. (cherry picked from commit 56a7f45)
27202d5 to
fe486e1
Compare
🟠 PR Severity: HIGH
🟠 High (1 file)
🟢 Low (1 file)
ℹ️ Excluded from severity calculation (1 file)
AnalysisThis PR is a backport of #10529 that fixes a backwards-compatibility issue in channel edge feature deserialization. The core change is in The fix addresses deserialization logic that could affect how channel features are read from the database. While this is a backwards-compatibility fix (generally lower risk than new features), it touches graph database code which is critical for routing and network state management. No severity bump applied:
This requires review by an engineer knowledgeable in the graph database and channel feature handling. To override, add a |
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces a critical fix for a backwards compatibility issue in channel edge feature deserialization, ensuring nodes can upgrade from v0.19.x to v0.20.x without database read errors. The changes are well-implemented and demonstrate a thorough understanding of the problem.
The core of the fix is the new deserializeChanEdgeFeatures helper function, which correctly handles both legacy (raw bytes) and new (length-prefixed) feature vector formats. The use of a canonical encoding check to disambiguate potential format collisions is a robust solution.
The accompanying tests are comprehensive, covering a wide range of scenarios including empty features, legacy and new formats, and specific edge cases where format detection could be ambiguous. The inclusion of property-based tests provides strong confidence in the correctness of the fix. The release note is clear and accurately describes the change.
Overall, this is an excellent contribution that addresses a significant bug with a clean and well-tested solution. I have no further comments.
Backport of #10529
This commit fixes a backwards compatibility issue that prevented nodes from upgrading from v0.19.x to v0.20.x.
In v0.19.x, channel edge features were serialized as raw feature bytes without a length prefix. In v0.20.x (commit 2f2845d), the serialization changed to use
Features.Encode()which adds a 2-byte big-endian length prefix before the feature bits. The deserialization code was updated to useFeatures.Decode()which expects this length prefix.When v0.20.x reads a database created by v0.19.x,
Decode()tries to read a length prefix that doesn't exist, causing an EOF error:The fix adds a
deserializeChanEdgeFeatures()helper that detects which format is being read and decodes accordingly:uint16(bytes[0:2]) == len(bytes)-2.DecodeBase256with the known length.The format detection is safe because in the legacy format, the first byte always has at least one bit set (the serialization uses minimum bytes), so the first two bytes can never encode a value equal to len-2.
Fixes #10528.