-
Notifications
You must be signed in to change notification settings - Fork 2
fix: use correct varint decoding for Handshake #439
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
Conversation
📝 WalkthroughWalkthroughThis change adds a new Handshake-specific varint implementation in internal/handshake/varint.go (ReadUvarint, ReadUvarintReader, WriteUvarint) implementing prefix-byte compact encoding and little-endian multi-byte forms. Call sites previously using binary.ReadUvarint or internal helpers were updated to use the new exported functions in block decoding, transaction decoding (including witness parsing), and protocol message encode/decode paths. The messages package removed internal uvarint helpers and now uses the exported functions. Tests for handshake block decoding were refactored to a table-driven format. Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Pre-merge checks and finishing touches✅ Passed checks (4 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
c0cf93a to
dd73d72
Compare
* move varint decode/encode from messages to common place * add additional block tests * use custom varint decode in block/transaction decode Fixes #438 Signed-off-by: Aurora Gaffney <[email protected]>
dd73d72 to
b5e0442
Compare
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.
No issues found across 5 files
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.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
internal/handshake/protocol/messages.go (1)
309-335: Fixmake()calls: convertuint64count tointin all message decodersThe decoded
countfromhandshake.ReadUvarintisuint64, butmake()requires anintlength parameter. This causes a compile-time type error in all four message decoders:
- MsgAddr.Decode (line 327):
m.Peers = make([]NetAddress, count)- MsgGetData.Decode (line 359):
m.Inventory = make([]InvItem, count)- MsgGetHeaders.Decode (line 393):
m.Locator = make([][32]byte, count)- MsgHeaders.Decode (line 424):
m.Headers = make([]*handshake.BlockHeader, count)The
for i := range countloops are valid under Go 1.22, but allocations must use anint-typed value.Convert
counttointafter the payload-length validation in each method:func (m *MsgAddr) Decode(data []byte) error { count, bytesRead, err := handshake.ReadUvarint(data) if err != nil { return err } data = data[bytesRead:] if len(data) != int(count*netAddressLength) { // nolint:gosec return errors.New("invalid payload length") } + peerCount := int(count) - m.Peers = make([]NetAddress, count) + m.Peers = make([]NetAddress, peerCount) - for i := range count { + for i := range peerCount { if err := m.Peers[i].Decode(data[:netAddressLength]); err != nil { return err } data = data[netAddressLength:] } return nil }Apply the same pattern to MsgGetData, MsgGetHeaders, and MsgHeaders with appropriate variable names (
invCount,locCount,hdrCount).internal/handshake/block_test.go (1)
18-61: The review comment is accurate and identifies a real critical compilation error.Verification findings:
decodeHexreturns[]byte— confirmed at lines 18-20- Invalid type conversion syntax — The code attempts
[32]byte(decodeHex(...))at lines 36, 41, 49, 54, 96, 115, and[24]byte(decodeHex(...))at line 46. In Go, slice-to-array conversion via cast is not valid syntax; this will fail compilation with "cannot convert" errors.- Struct fields expect arrays — Confirmed from
internal/handshake/block.go:
PrevBlock,NameRoot,WitnessRoot,MerkleRootare[32]byteExtraNonceis[24]byteOutpoint.Hashis[32]byte- No helpers exist — No
bytes32,bytes24, or similar conversion helpers found in the codebase- Proposed solution is idiomatic — Using
copy()helpers is the standard Go pattern for this scenarioConclusion: The code will not compile without the suggested fix. The review comment's recommendation to add
bytes32()andbytes24()helper functions is correct and necessary.
🧹 Nitpick comments (1)
internal/handshake/varint.go (1)
17-69: Varint implementation matches CompactSize; consider adding focused encode/decode tests
ReadUvarintReader/ReadUvarintandWriteUvarintcorrectly implement the expected CompactSize-style varint layout (1/3/5/9-byte forms with 0xfd/0xfe/0xff prefixes) and centralized error handling for truncated multi-byte values. This is exactly what the block/transaction/message decoders needed.Given how central this utility now is, it would be worthwhile to add small, direct unit tests here (round-trips for boundary values like
0xfc,0xfd,math.MaxUint16,math.MaxUint32, and a largeuint64), so regressions in varint handling are caught closer to the source.Also applies to: 72-91
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
internal/handshake/block.go(1 hunks)internal/handshake/block_test.go(1 hunks)internal/handshake/protocol/messages.go(8 hunks)internal/handshake/transaction.go(3 hunks)internal/handshake/varint.go(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
internal/handshake/protocol/messages.go (1)
internal/handshake/varint.go (2)
WriteUvarint(72-91)ReadUvarint(17-27)
internal/handshake/block.go (1)
internal/handshake/varint.go (1)
ReadUvarintReader(29-70)
internal/handshake/transaction.go (1)
internal/handshake/varint.go (1)
ReadUvarintReader(29-70)
🔇 Additional comments (2)
internal/handshake/block.go (1)
48-58: Switch to shared CompactSize reader is correct and aligns with Handshake encodingUsing
ReadUvarintReader(r)here fixes the earlier misuse ofbinary.ReadUvarint(LEB128) for Handshake’s CompactSize varints and centralizes the logic with the other decode paths. The surrounding loop and error handling remain appropriate.internal/handshake/transaction.go (1)
52-75: The code is correct for Go 1.24—no changes neededGo 1.22 and later (including the target Go 1.24.0) allow
make()to accept any integer type, includinguint64, without explicit conversion. The current code compiles without error:
i.Witness = make([][]byte, witnessCount)is valid (witnessCount is uint64)for j := range witnessCountis valid (Go 1.22+ supports range over integers)i.Witness[j] = make([]byte, itemLength)is valid (itemLength is uint64)No type conversion is required.
Likely an incorrect or invalid review comment.
|
@cubic-dev-ai please review this |
@agaffney I've started the AI code review. It'll take a few minutes to complete. |
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.
No issues found across 5 files
Fixes #438
Summary by cubic
Fixes incorrect varint (CompactSize) decoding for Handshake by introducing a shared implementation and using it across blocks, transactions, and protocol messages. Adds new block tests and hash checks to prevent regressions. Fixes #438.
Bug Fixes
Refactors
Written for commit b5e0442. Summary will update automatically on new commits.
Summary by CodeRabbit
Refactor
Tests
✏️ Tip: You can customize this high-level summary in your review settings.