-
Notifications
You must be signed in to change notification settings - Fork 21
Generate report IDs #701
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: 04-04-add_payer_report_protos
Are you sure you want to change the base?
Generate report IDs #701
Conversation
WalkthroughThis update introduces new functionality in the payerreport package to support Ethereum smart contract interactions for payer reports. A new file defines argument structures for encoding report data. The Changes
Sequence Diagram(s)sequenceDiagram
participant T as Test
participant PR as PayerReport
participant H as HashPayerReportInput (utils)
T->>PR: Call ID()
PR->>PR: Pack report fields (including node data)
PR->>H: Compute Keccak256 hash on packed bytes
H-->>PR: Return 32-byte hash
PR-->>T: Return unique identifier (ID)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 golangci-lint (1.64.8)Error: you are using a configuration file for golangci-lint v2 with golangci-lint v1: please use golangci-lint v2 Tip ⚡💬 Agentic Chat (Pro Plan, General Availability)
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (5)
🚧 Files skipped from review as they are similar to previous changes (5)
⏰ Context from checks skipped due to timeout of 90000ms (8)
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
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
🧹 Nitpick comments (11)
pkg/utils/hash.go (1)
35-37
: Consider adding a domain separation label for consistencyThe new
HashPayerReportInput
function takes a different approach compared to other hash functions in this file - it doesn't use any domain separation label. While this may be intentional based on your requirements, adding a domain separation label would be consistent with the pattern established by other hash functions (HashPayerSignatureInput
,HashJWTSignatureInput
, etc.).func HashPayerReportInput(packedBytes []byte) []byte { - return ethcrypto.Keccak256(packedBytes) + return ethcrypto.Keccak256( + []byte(constants.PAYER_REPORT_DOMAIN_SEPARATION_LABEL), + packedBytes, + ) }This would require defining a new constant in the constants package.
pkg/utils/slice.go (1)
3-7
: Add validation for input slice lengthThe current implementation silently truncates input slices longer than 32 bytes, which could lead to unexpected behavior. Consider adding validation or documentation to make this behavior explicit.
func SliceToArray32(slice []byte) [32]byte { var array [32]byte copy(array[:], slice) + // Note: If slice is longer than 32 bytes, only the first 32 bytes are used return array }
Alternatively, if truncation is undesirable:
func SliceToArray32(slice []byte) ([32]byte, error) { var array [32]byte + if len(slice) > 32 { + return array, fmt.Errorf("input slice length %d exceeds maximum of 32 bytes", len(slice)) + } copy(array[:], slice) return array, nil }pkg/payerreport/report_test.go (2)
9-24
: Enhance test coverage with multiple test casesThe current test validates basic functionality but only tests one set of input values. Consider adding multiple test cases with different inputs to ensure robustness, including edge cases.
func TestPayerReportID(t *testing.T) { - report := PayerReport{ - OriginatorNodeID: 1, - StartSequenceID: 1, - EndSequenceID: 10, - PayersMerkleRoot: []byte{1, 2, 3}, - PayersLeafCount: 1, - NodesMerkleRoot: []byte{4, 5, 6}, - NodesLeafCount: 1, - } - - id, err := report.ID() - require.NoError(t, err) - require.NotNil(t, id) - require.Len(t, id, 32) + testCases := []struct { + name string + report PayerReport + wantErr bool + }{ + { + name: "valid report", + report: PayerReport{ + OriginatorNodeID: 1, + StartSequenceID: 1, + EndSequenceID: 10, + PayersMerkleRoot: []byte{1, 2, 3}, + PayersLeafCount: 1, + NodesMerkleRoot: []byte{4, 5, 6}, + NodesLeafCount: 1, + }, + wantErr: false, + }, + { + name: "zeros", + report: PayerReport{ + OriginatorNodeID: 0, + StartSequenceID: 0, + EndSequenceID: 0, + PayersMerkleRoot: make([]byte, 0), + PayersLeafCount: 0, + NodesMerkleRoot: make([]byte, 0), + NodesLeafCount: 0, + }, + wantErr: false, + }, + // Add more test cases as needed + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + id, err := tc.report.ID() + if tc.wantErr { + require.Error(t, err) + return + } + require.NoError(t, err) + require.NotNil(t, id) + require.Len(t, id, 32) + }) + } }
14-17
: Consider validating the actual ID valueThe test only checks that the ID is not nil and has the expected length, but it doesn't validate that the actual ID value is correct. Consider adding an expected value check to ensure the ID generation logic is working as intended.
func TestPayerReportID(t *testing.T) { report := PayerReport{ OriginatorNodeID: 1, StartSequenceID: 1, EndSequenceID: 10, PayersMerkleRoot: []byte{1, 2, 3}, PayersLeafCount: 1, NodesMerkleRoot: []byte{4, 5, 6}, NodesLeafCount: 1, } id, err := report.ID() require.NoError(t, err) require.NotNil(t, id) require.Len(t, id, 32) + // Expected ID value (precomputed) + expectedID := [32]byte{ + // Fill in the expected bytes here + } + require.Equal(t, expectedID, id, "ID does not match expected value") }pkg/payerreport/id.go (2)
5-34
: Missing documentation for the payerReportMessageHash variableConsider adding documentation to explain the purpose of this variable and how it's used in the context of the application. This would help other developers understand its role in the report ID generation process.
+// payerReportMessageHash defines the Ethereum ABI encoding structure used for packing +// PayerReport data before hashing for ID generation or smart contract interactions. +// Each field maps to a corresponding field in the PayerReport struct with appropriate +// types for Ethereum compatibility. var payerReportMessageHash = abi.Arguments{ { Name: "originatorNodeID", Type: abi.Type{T: abi.UintTy, Size: 32}, }, // ... rest of the definition }
5-34
: Consider making variable unexported if it's not used outside the packageIf
payerReportMessageHash
is only used internally within thepayerreport
package, consider making it unexported (lowercase first letter) to follow Go's visibility conventions.-var payerReportMessageHash = abi.Arguments{ +var payerReportMessageHash = abi.Arguments{If it's intended to be used by other packages, then it should have proper documentation as per the previous comment.
pkg/payerreport/interface.go (5)
31-41
: Consider adding function documentation.The
ToProto()
method correctly maps the struct fields to their protobuf representation, but lacks documentation explaining its purpose and return value.Add a comment before the function:
+// ToProto converts a PayerReport to its Protocol Buffers representation func (p *PayerReport) ToProto() *proto.PayerReport {
43-58
: Consider adding nil checks for merkle root fields.The method doesn't verify if
p.PayersMerkleRoot
orp.NodesMerkleRoot
are nil before passing them toutils.SliceToArray32
. If these could be nil, consider adding validation.func (p *PayerReport) ID() ([]byte, error) { + if p.PayersMerkleRoot == nil || p.NodesMerkleRoot == nil { + return nil, fmt.Errorf("merkle root fields cannot be nil") + } packedBytes, err := payerReportMessageHash.Pack(
43-58
: Add documentation for the ID method.The
ID()
method should include documentation explaining its purpose, return value, and possible errors.+// ID computes a unique identifier for the PayerReport by packing its fields and returning the keccak256 hash +// Returns the hash as a byte slice and any error that occurred during packing func (p *PayerReport) ID() ([]byte, error) {
44-52
: The payerReportMessageHash variable is not defined in this file.The code refers to
payerReportMessageHash
which appears to be defined elsewhere. Consider adding a comment referencing where this variable is defined to improve code readability.func (p *PayerReport) ID() ([]byte, error) { + // payerReportMessageHash is defined in pkg/payerreport/id.go packedBytes, err := payerReportMessageHash.Pack(
53-55
: Consider adding more context to the error.When returning an error from
Pack()
, add more context to help with debugging.if err != nil { - return nil, err + return nil, fmt.Errorf("failed to pack payer report: %w", err) }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
pkg/payerreport/id.go
(1 hunks)pkg/payerreport/interface.go
(2 hunks)pkg/payerreport/report_test.go
(1 hunks)pkg/utils/hash.go
(1 hunks)pkg/utils/slice.go
(1 hunks)
🧰 Additional context used
🧬 Code Definitions (2)
pkg/payerreport/report_test.go (1)
pkg/payerreport/interface.go (1)
PayerReport
(12-29)
pkg/payerreport/interface.go (2)
pkg/utils/slice.go (1)
SliceToArray32
(3-7)pkg/utils/hash.go (1)
HashPayerReportInput
(35-37)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: Upgrade Tests
🔇 Additional comments (4)
pkg/payerreport/id.go (1)
5-34
:❓ Verification inconclusive
Verify sizes match Solidity contract expectations
Ensure that the sizes defined in these ABI arguments match the expectations of the Solidity smart contract that will be interacting with this data. For example, the definition uses
UintTy, Size: 32
for the originatorNodeID, which would be auint256
in Solidity.Please verify that these type definitions match the corresponding smart contract structure:
- originatorNodeID: uint256 (UintTy, Size: 32)
- startSequenceID: uint64 (UintTy, Size: 64)
- endSequenceID: uint64 (UintTy, Size: 64)
- payersMerkleRoot: bytes32 (FixedBytesTy, Size: 32)
- payersLeafCount: uint32 (UintTy, Size: 32)
- nodesMerkleRoot: bytes32 (FixedBytesTy, Size: 32)
- nodesLeafCount: uint32 (UintTy, Size: 32)
🏁 Script executed:
#!/bin/bash # Find smart contract files and check for PayerReport structure definitions rg -t solidity -A 10 "struct PayerReport" || rg -t solidity -A 10 "function.*PayerReport"Length of output: 156
Verify ABI Type Mappings Against Solidity Contract
The ABI definitions in
pkg/payerreport/id.go
appear to follow the intended Solidity types:
- originatorNodeID:
UintTy, Size: 32
should correspond to Solidity’suint256
- startSequenceID & endSequenceID:
UintTy, Size: 64
should map to Solidity’suint64
- payersMerkleRoot & nodesMerkleRoot:
FixedBytesTy, Size: 32
match Solidity’sbytes32
- payersLeafCount & nodesLeafCount:
UintTy, Size: 32
should correspond to Solidity’suint32
I attempted to locate the Solidity definitions (e.g. a
struct PayerReport
) using a file-type filter, but the query using-t solidity
failed due to an unsupported file type. To ensure confidence, please verify manually (or update the search criteria) that the Solidity smart contract indeed declares the expected types for thePayerReport
structure.pkg/payerreport/interface.go (3)
8-9
: Good additions to the imports.The added imports support the new functionality - proto package for the protobuf conversion and utils package for hashing and byte array operations.
25-28
: Good addition of node-related fields with clear documentation.The new fields
NodesMerkleRoot
andNodesLeafCount
are well-documented and follow the same pattern as the existing payer-related fields.
31-41
:❓ Verification inconclusive
Verify all necessary fields are mapped in the protobuf conversion.
The
Payers
field from the struct is not included in the protobuf mapping. Is this intentional or an oversight?
🏁 Script executed:
#!/bin/bash # Check the proto definition to see if it has a field for Payers grep -rn "message PayerReport" --include="*.proto" .Length of output: 54
Action Required: Verify Proto Field Mapping for
PayerReport
Our initial automated search for a proto definition (using the pattern
"message PayerReport"
) did not yield any output, so we couldn’t confirm whether the corresponding protobuf message is defined with aPayers
field. As a result, it's unclear if the omission of thePayers
field in theToProto
conversion is intentional.
- Verify the Proto Definition Manually: Please check the repository’s proto files to determine if the
PayerReport
message includes a field forPayers
.- Mapping Confirmation: If the proto message is meant to include the
Payers
field, update theToProto
function inpkg/payerreport/interface.go
(lines 31-41) to include it. Otherwise, add a clarifying comment indicating that the omission is intentional.
1599a16
to
b5f8759
Compare
0dd174f
to
139fa98
Compare
TL;DR
Added functionality to generate unique IDs for payer reports based on their contents.
What changed?
ID()
method to thePayerReport
struct that generates a unique identifier by hashing the report's fieldspayerreport/id.go
file with ABI definitions for hashing payer report dataNodesMerkleRoot
andNodesLeafCount
fields to thePayerReport
structToProto()
method to convert aPayerReport
to its protobuf representationHow to test?
Run the new test in
pkg/payerreport/report_test.go
to verify that the ID generation works correctly:Why make this change?
This change enables unique identification of payer reports based on their content, which is necessary for tracking, referencing, and validating reports throughout the system. The ID generation follows Ethereum's ABI encoding standards to ensure compatibility with smart contract verification.
Summary by CodeRabbit
New Features
Tests