-
Notifications
You must be signed in to change notification settings - Fork 347
fix: change proof functions to return values instead of pointers #2358
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
base: main
Are you sure you want to change the base?
Conversation
- Change ProofsFromByteSlices to return []Proof instead of []*Proof - Change ProofFromProto to return Proof instead of *Proof - Change ProofsFromLeafHashes to return []Proof instead of []*Proof - Update all call sites to remove pointer dereferences - Convert RowProof.Proofs field to []merkle.Proof for consistency - Update helper functions to provide pointers where needed for external APIs Co-authored-by: tzdybal <[email protected]>
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.
Some more *Proofs can be easily changed to Proof.
@copilot please address review comments.
consensus/propagation/types/types.go
Outdated
| return nil, errors.New("invalid number of partset hashes") | ||
| } | ||
|
|
||
| c.proofsCache = make([]*merkle.Proof, 0, len(c.PartsHashes)) |
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.
As you're changing everything to reduce pointers, you might as well change proofsCache to []merkle.Proof instead of changing loops below.
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.
Fixed in 47f748c. Changed proofsCache field from []*merkle.Proof to []merkle.Proof and updated the loops to directly assign values instead of taking addresses.
consensus/propagation/types/types.go
Outdated
| Index: r.Index, | ||
| Data: r.Data, | ||
| Proof: proof, | ||
| Proof: &proof, |
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.
Can RecoveryPart.Proof also be of type Proof and not *Proof? analyze usages to see if it's viable option.
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.
Fixed in 47f748c. Changed RecoveryPart.Proof from *merkle.Proof to merkle.Proof. Analyzed all usages and updated the validation logic to check for zero value instead of nil, and updated all call sites including tests.
| {"empty proof", &Proof{}, false}, | ||
| {"failure nil", nil, false}, | ||
| {"success", proofs[0], true}, | ||
| {"success", &proofs[0], true}, |
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.
Change v1 in testCases struct to Proof instead of referencing here and dereferencing in line 197.
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.
Fixed in 47f748c. Updated the test case to handle the nil case separately and removed the dereference in the comparison, while maintaining the same test coverage.
rpc/core/blocks.go
Outdated
| _, proofs := merkle.ProofsFromByteSlices(dataRootEncodedTuples) | ||
| //nolint:gosec | ||
| return proofs[height-int64(tuples[0].height)], nil | ||
| return &proofs[height-int64(tuples[0].height)], nil |
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.
Is this needed? Can't we return merkle.Proof from this function?
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.
Fixed in 47f748c. Changed proveDataRootTuples to return merkle.Proof directly instead of *merkle.Proof. The caller now takes the address when needed to maintain API compatibility with the external interface that still expects a pointer.
|
@copilot please address the review comments. |
Co-authored-by: tzdybal <[email protected]>
consensus/propagation/types/types.go
Outdated
| } | ||
|
|
||
| c.proofsCache = make([]*merkle.Proof, 0, len(c.PartsHashes)) | ||
| c.proofsCache = make([]merkle.Proof, 0, len(c.PartsHashes)) |
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.
@copilot, is the size of slice optimal? Elements are added in 2 loops, it seems reallocation will always happen, but we can avoid it. Please verify and fix if needed.
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.
Fixed in 86ce837. Optimized slice allocation by pre-allocating with exact size make([]merkle.Proof, len(c.PartsHashes)) and using direct index assignment instead of append to eliminate any reallocation.
|
@copilot rebase changes on current main. |
Co-authored-by: tzdybal <[email protected]>
|
is this still a draft? if so, then we should close due to staleness imo |
This PR addresses an inconsistency in the merkle proof API where functions return pointers but callers immediately dereference them to values, creating unnecessary indirection and potential performance overhead.
Problem
The following functions were returning pointers that callers consistently dereferenced:
ProofsFromByteSlicesreturned[]*ProofProofFromProtoreturned*ProofProofsFromLeafHashesreturned[]*ProofAdditionally, several struct fields and internal functions maintained pointer semantics when value semantics would be more efficient and clearer:
CompactBlock.proofsCachewas[]*merkle.ProofRecoveryPart.Proofwas*merkle.Proof[]*merkle.ProofCall sites throughout the codebase immediately converted these to values:
Solution
Changed the functions and fields to use values directly:
ProofsFromByteSlicesnow returns[]ProofProofFromProtonow returnsProofProofsFromLeafHashesnow returns[]ProofCompactBlock.proofsCacheis now[]merkle.ProofRecoveryPart.Proofis nowmerkle.ProofThis eliminates the unnecessary pointer allocations and dereferences:
Performance Optimization
Additionally optimized slice allocation in
CompactBlock.Proofs()to eliminate potential reallocations by pre-allocating with exact size and using direct index assignment instead of append operations.Benefits
*Proofobjects that are immediately copiedProofstruct contains only simple fields (int64,[]byte,[][]byte), making value copies efficient (shallow copy of slice headers)Changes
crypto/merkle/proof.gotypes/,rpc/, andconsensus/packagesAll existing functionality is preserved - this is purely an API improvement that eliminates unnecessary indirection while adding performance optimizations.
Fixes #2357.
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.