Skip to content
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

feat: standard non-evm inbound memo #2987

Merged
merged 23 commits into from
Oct 16, 2024
Merged

feat: standard non-evm inbound memo #2987

merged 23 commits into from
Oct 16, 2024

Conversation

ws4charlie
Copy link
Contributor

@ws4charlie ws4charlie commented Oct 10, 2024

Description

  • Created struct type InboundMemo as the standard memo.
  • Implemented two APIs EncodeToBytes and DecodeFromBytes according to rfc PR
  • Support for two encoding formats: ABI encoding, compact encoding

Hot to pack your own inbound memo?

Step-1: prepare a memo header

func MakeHead() []byte {
	header := make([]byte, 4)
	header[0] = 'Z'
	header[1] = 0<<4 | 0b0010 // version + encoding format (e.g. compact long)
	header[2] = 0b0001 << 4   // operation code (e.g. DepositAndCall)
	header[3] = 0b00000011    // 'payload' and 'revertAddress' are set
	return header
}

Step-2: pack the memo fields with encoding format (ABI or compact) that suites your use case

The follow example code packs the fields using ABI format

func ABIPack(receiver common.Address, payload []byte, revertAddress string) ([]byte, error) {
	// define the ABI for encoding the types: address, bytes, string
	abiString := `[{"type":"function","name":"encode","inputs":[
		{"type":"address"},
		{"type":"bytes"},
		{"type":"string"}],
		"outputs":[]}]`

	// parse the ABI
	parsedABI, err := abi.JSON(strings.NewReader(abiString))
	if err != nil {
		return nil, err
	}

	// pack the values using the ABI
	data, err := parsedABI.Pack("encode", receiver, payload, revertAddress)
	if err != nil {
		return nil, err
	}

	// remove the 4-byte selector
	return data[4:], nil
}

For use cases that are sensitive to transaction size, the follow example packs the fields using compact format

func CompactPack(receiver common.Address, payload []byte, revertAddress string) []byte {
	data := make([]byte, 0)

	// pack receiver (fixed 20	bytes)
	data = append(data, receiver.Bytes()...)

	// pack payload (dynamic)
	// encode length with 1 byte if 'compact short' is your choice
	lenthPayload := make([]byte, 2)
	binary.LittleEndian.PutUint16(lenthPayload, uint16(len(payload)))

	data = append(data, lenthPayload...) // write length
	data = append(data, payload...)      // write payload

	// pack revert address (dynamic).
	// encode length with 1 byte if 'compact short' is your choice
	lengthRevertAddr := make([]byte, 2)
	binary.LittleEndian.PutUint16(lengthRevertAddr, uint16(len([]byte(revertAddress))))

	data = append(data, lengthRevertAddr...)      // write length
	data = append(data, []byte(revertAddress)...) // write revert address

	return data
}

How Has This Been Tested?

  • Tested CCTX in localnet
  • Tested in development environment
  • Go unit tests
  • Go integration tests
  • Tested via GitHub Actions

Summary by CodeRabbit

  • New Features

    • Introduced support for stateful precompiled contracts and a staking precompiled contract.
    • Added Bitcoin TSS address derivation by chain ID and static info for various Bitcoin testnets.
    • Implemented a non-EVM standard inbound memo package.
    • Established a structured approach for codec arguments and memo handling for non-EVM chains.
  • Bug Fixes

    • Resolved issues with operators voting on discarded keygen ballots.
    • Improved error handling and informative messages during node startup.
  • Tests

    • Added comprehensive unit tests for new functionalities, including codec operations and memo handling.
  • Refactor

    • Enhanced code quality by fixing lint errors and refactoring functions for improved parameter handling.

@ws4charlie ws4charlie marked this pull request as ready for review October 10, 2024 16:52
Copy link
Contributor

coderabbitai bot commented Oct 10, 2024

📝 Walkthrough

Walkthrough

The pull request introduces a series of enhancements across various modules, including the addition of new features, refactoring of existing code, and improvements to testing and CI processes. Key features include support for stateful precompiled contracts, enhancements for Bitcoin integration, and the introduction of a codec system for handling memo fields. Additionally, several new files are created to manage bit manipulation, codec arguments, and memo structures, while existing dependencies are updated in the go.mod file to ensure compatibility and functionality.

Changes

File Change Summary
changelog.md Updated to reflect new features, refactoring, tests, fixes, and CI improvements. Notable features include stateful precompiled contracts and Bitcoin support enhancements.
go.mod Added new dependencies, updated existing ones, and replaced several modules with specific versions or forks.
pkg/math/bits.go Introduced functions for bit manipulation: SetBit, IsBitSet, GetBits, and SetBits.
pkg/math/bits_test.go Added unit tests for bit manipulation functions.
pkg/memo/arg.go Added types and functions for codec arguments, including ArgType enumeration and CodecArg struct.
pkg/memo/arg_test.go Introduced tests for the NewArg function and various argument types.
pkg/memo/codec.go Established a codec system for various encoding formats, defining constants and a Codec interface.
pkg/memo/codec_abi.go Introduced CodecABI struct for handling ABI encoded memo fields, with methods for adding, packing, and unpacking arguments.
pkg/memo/codec_abi_test.go Added unit tests for CodecABI functionalities.
pkg/memo/codec_compact.go Created CodecCompact type for compact encoding and decoding of memo fields.
pkg/memo/codec_compact_test.go Added tests for CodecCompact functionalities.
pkg/memo/codec_test.go Introduced tests for GetLenBytes and GetCodec functions.
pkg/memo/fields.go Added Fields interface with methods for packing, unpacking, and validating memo fields.
pkg/memo/fields_v0.go Introduced FieldsV0 struct with methods for handling inbound memo version 0.
pkg/memo/fields_v0_test.go Added tests for FieldsV0 methods.
pkg/memo/header.go Created Header struct for memo headers with encoding and decoding methods.
pkg/memo/header_test.go Added tests for Header struct methods.
pkg/memo/memo.go Introduced InboundMemo struct for handling inbound memos with encoding and decoding methods.
pkg/memo/memo_test.go Added tests for InboundMemo encoding and decoding functionalities.
testutil/sample/memo.go Introduced helper functions for memoization and data packing related to Ethereum smart contracts.

Possibly related PRs

  • chore: sync v20 changelog #2872: The changelog updates in this PR reflect significant changes in functionality similar to the updates made in the main PR, particularly regarding enhancements for Bitcoin support and the introduction of new features in the protocol.

Suggested labels

no-changelog

Suggested reviewers

  • swift1337
  • skosito
  • kingpinXD
  • brewmaster012
  • lumtis
  • fbac

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

codecov bot commented Oct 10, 2024

Codecov Report

Attention: Patch coverage is 96.73025% with 12 lines in your changes missing coverage. Please review.

Project coverage is 66.25%. Comparing base (7b2bbe7) to head (49ef1d8).
Report is 1 commits behind head on develop.

Files with missing lines Patch % Lines
pkg/memo/memo.go 89.74% 4 Missing ⚠️
pkg/memo/codec_abi.go 93.54% 1 Missing and 1 partial ⚠️
pkg/memo/codec_compact.go 98.47% 1 Missing and 1 partial ⚠️
pkg/memo/fields_v0.go 97.29% 1 Missing and 1 partial ⚠️
zetaclient/chains/bitcoin/observer/inbound.go 0.00% 1 Missing ⚠️
zetaclient/compliance/compliance.go 0.00% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop    #2987      +/-   ##
===========================================
+ Coverage    65.77%   66.25%   +0.48%     
===========================================
  Files          398      406       +8     
  Lines        22421    22772     +351     
===========================================
+ Hits         14747    15088     +341     
- Misses        6900     6907       +7     
- Partials       774      777       +3     
Files with missing lines Coverage Δ
pkg/chains/conversion.go 100.00% <ø> (ø)
pkg/math/bits/bits.go 100.00% <100.00%> (ø)
pkg/memo/arg.go 100.00% <100.00%> (ø)
pkg/memo/codec.go 100.00% <100.00%> (ø)
pkg/memo/header.go 100.00% <100.00%> (ø)
x/crosschain/keeper/evm_deposit.go 86.95% <100.00%> (ø)
zetaclient/chains/evm/observer/inbound.go 37.44% <100.00%> (ø)
zetaclient/chains/bitcoin/observer/inbound.go 18.90% <0.00%> (ø)
zetaclient/compliance/compliance.go 10.00% <0.00%> (ø)
pkg/memo/codec_abi.go 93.54% <93.54%> (ø)
... and 3 more

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 47

🧹 Outside diff range and nitpick comments (33)
pkg/memo/fields.go (4)

3-4: Enhance the interface documentation.

The current comment for the Fields interface is concise but could be more informative. Consider expanding it to provide more context about the purpose and usage of this interface in relation to memo operations.

Suggested improvement:

// Fields defines the interface for memo field operations.
// It provides methods for encoding, decoding, and validating memo fields
// used in various operations within the system.
type Fields interface {
    // ... (rest of the interface)
}

5-6: Enhance the Pack method documentation.

While the current comment for the Pack method is concise, it could be more informative. Consider expanding it to provide more details about the parameters and return values.

Suggested improvement:

// Pack encodes the memo fields based on the given operation code and encoding format.
// It returns a data flag byte, the encoded data as a byte slice, and any error encountered during encoding.
// Parameters:
//   - opCode: uint8 representing the operation code
//   - encodingFormat: uint8 specifying the encoding format to be used
// Returns:
//   - byte: data flag
//   - []byte: encoded memo fields
//   - error: any error encountered during the encoding process
Pack(opCode, encodingFormat uint8) (byte, []byte, error)

8-9: Enhance the Unpack method documentation.

The current comment for the Unpack method is concise but could be more informative. Consider expanding it to provide more details about the parameters and return value.

Suggested improvement:

// Unpack decodes the memo fields from the provided data.
// It uses the given operation code, encoding format, and data flags to interpret the data correctly.
// Parameters:
//   - opCode: uint8 representing the operation code
//   - encodingFormat: uint8 specifying the encoding format used
//   - dataFlags: uint8 containing additional flags for decoding
//   - data: []byte containing the encoded memo fields
// Returns:
//   - error: any error encountered during the decoding process
Unpack(opCode, encodingFormat, dataFlags uint8, data []byte) error

11-12: Enhance the Validate method documentation.

The current comment for the Validate method is concise but could be more informative. Consider expanding it to provide more details about the parameter and return value.

Suggested improvement:

// Validate checks if the memo fields are valid for the given operation code.
// It performs necessary validations based on the specific requirements of each operation.
// Parameter:
//   - opCode: uint8 representing the operation code to validate against
// Returns:
//   - error: nil if the fields are valid, or an error describing the validation failure
Validate(opCode uint8) error
pkg/math/bits.go (4)

7-13: SetBit function is well-implemented, with a potential for optimization.

The function correctly sets the specified bit and handles invalid positions. However, consider using a constant for the maximum valid position to improve readability and maintainability.

Consider applying this optimization:

+const maxBitPosition = 7

 func SetBit(b *byte, position uint8) {
-	if position > 7 {
+	if position > maxBitPosition {
 		return
 	}
 	*b |= 1 << position
 }

15-22: IsBitSet function is well-implemented, with room for consistency improvement.

The function correctly checks the specified bit and handles invalid positions. For consistency with the SetBit function, consider using the same constant for the maximum valid position.

Consider applying this change for consistency:

+const maxBitPosition = 7

 func IsBitSet(b byte, position uint8) bool {
-	if position > 7 {
+	if position > maxBitPosition {
 		return false
 	}
 	bitMask := byte(1 << position)
 	return b&bitMask != 0
 }

24-35: GetBits function is efficiently implemented, with potential for improved clarity.

The function correctly extracts and processes the bits according to the given mask. The use of bits.TrailingZeros8 is an efficient approach. To improve clarity, consider adding a comment explaining the purpose of the right shift operation.

Consider adding this explanatory comment:

 func GetBits(b byte, mask byte) byte {
 	extracted := b & mask

 	// get the number of trailing zero bits
 	trailingZeros := bits.TrailingZeros8(mask)

+	// right shift to remove trailing zeros, effectively normalizing the extracted value
 	return extracted >> trailingZeros
 }

37-52: SetBits function is well-implemented, with room for consistency and clarity improvements.

The function correctly sets the specified bits according to the given mask and value. The bitwise operations are efficient and the logic is sound. To improve consistency and clarity, consider extracting the TrailingZeros8 call to a separate variable with a descriptive name, similar to the GetBits function.

Consider applying this change for consistency and clarity:

 func SetBits(b byte, mask byte, value byte) byte {
 	// get the number of trailing zero bits in the mask
-	trailingZeros := bits.TrailingZeros8(mask)
+	trailingZeros := bits.TrailingZeros8(mask)
+
+	// shift the value left to align with the mask
+	valueAligned := value << trailingZeros

-	// shift the value left by the number of trailing zeros
-	valueShifted := value << trailingZeros
-
 	// clear the bits in 'b' that correspond to the mask
 	bCleared := b &^ mask

 	// Set the bits by ORing the cleared 'b' with the shifted value
-	return bCleared | valueShifted
+	return bCleared | valueAligned
 }
pkg/memo/arg_test.go (3)

11-15: Test function declaration and data setup are well-structured.

The test function name Test_NewArg follows Go testing conventions. Sample data is appropriately generated using utility functions.

Consider adding comments to explain the purpose of each sample data variable:

// Sample Ethereum address for testing
argAddress := sample.EthAddress()

// Sample string for testing
argString := sample.String()

// Sample byte array for testing
argBytes := sample.Bytes()

16-46: Test cases are well-defined and cover various scenarios.

The table-driven testing approach is appropriate for testing multiple scenarios of the NewArg function. The test cases cover different argument types and use cases.

To improve test coverage, consider adding edge cases:

  1. Add a test case with an empty string for the revertAddress.
  2. Include a test case with a zero-length byte array for the payload.
  3. Add a test case with the maximum allowed length for each argument type.

Example addition:

{
    name:    "empty_revert_address",
    argType: "string",
    arg:     new(string), // Empty string
},
{
    name:    "empty_payload",
    argType: "bytes",
    arg:     &[]byte{}, // Empty byte array
},
// Add more edge cases here

48-70: Test execution and assertions are comprehensive.

The test execution follows best practices for table-driven tests. Assertions cover all relevant properties of the created argument, and the switch statement ensures that the correct helper function is used for each argument type.

To improve error messages in case of test failures, consider using require.Equal with custom messages:

require.Equal(t, tt.name, arg.Name, "Argument name mismatch")
require.Equal(t, memo.ArgType(tt.argType), arg.Type, "Argument type mismatch")
require.Equal(t, tt.arg, arg.Arg, "Argument value mismatch")

// In the switch statement
require.Equal(t, arg, memo.ArgReceiver(&argAddress), "ArgReceiver mismatch")
// Apply similar changes to other cases

This will provide more context in case of test failures, making it easier to identify and fix issues.

pkg/memo/codec_test.go (2)

10-51: Well-structured table-driven test for GetLenBytes.

The test covers various scenarios effectively, including error cases. To enhance maintainability, consider extracting the test cases into a separate variable or function.

Example refactoring:

var getLenBytesTestCases = []struct {
    name        string
    encodingFmt uint8
    expectedLen int
    expectErr   bool
}{
    // ... (existing test cases)
}

func Test_GetLenBytes(t *testing.T) {
    for _, tc := range getLenBytesTestCases {
        // ... (existing test logic)
    }
}

This separation allows for easier management of test cases and potential reuse in other tests.


53-92: Well-structured table-driven test for GetCodec.

The test effectively covers various scenarios, including error cases. To enhance the test's robustness, consider the following improvements:

  1. Extract test cases into a separate variable or function, similar to the suggestion for Test_GetLenBytes.

  2. Add more specific assertions for the returned codec. For example:

codec, err := memo.GetCodec(tc.encodingFmt)
if tc.errMsg != "" {
    require.Error(t, err)
    require.Nil(t, codec)
    require.Contains(t, err.Error(), tc.errMsg)
} else {
    require.NoError(t, err)
    require.NotNil(t, codec)
    // Add specific assertions based on the expected codec type
    switch tc.encodingFmt {
    case memo.EncodingFmtABI:
        require.IsType(t, &memo.ABICodec{}, codec)
    case memo.EncodingFmtCompactShort, memo.EncodingFmtCompactLong:
        require.IsType(t, &memo.CompactCodec{}, codec)
    }
}

These changes will provide more comprehensive validation of the GetCodec function's behavior.

pkg/math/bits_test.go (3)

10-44: Comprehensive test cases for SetBit function.

The TestSetBit function is well-structured and covers essential scenarios, including edge cases. The use of table-driven tests enhances maintainability and readability.

Consider adding the following test cases to further improve coverage:

  1. Setting a bit that's already set.
  2. Setting multiple bits in sequence.
  3. Setting all bits (0xFF).
    These additions would provide a more exhaustive test suite for the SetBit function.

46-85: Well-structured test cases for IsBitSet function.

The TestIsBitSet function is well-organized and covers crucial scenarios, including edge cases. The consistent use of table-driven tests enhances code maintainability.

To further strengthen the test suite, consider adding a test case for checking all bits set (0xFF). This would ensure the function behaves correctly when all bits are set to 1.


134-171: Well-structured test cases for SetBits function with room for improvement.

The TestSetBits function is well-organized and covers important scenarios for setting bits in different parts of a byte. The consistent use of table-driven tests enhances maintainability.

To further improve the test coverage, consider adding the following test cases:

  1. Setting all bits (mask: 0xFF, value: 0xFF)
  2. Setting no bits (mask: 0x00, any value)
  3. Setting bits when the initial byte is 0x00
  4. Setting bits when the initial byte is 0xFF
    These additional cases would provide a more comprehensive test suite for the SetBits function.
pkg/memo/header_test.go (4)

11-49: Comprehensive test coverage for Header_EncodeToBytes.

The test function Test_Header_EncodeToBytes demonstrates a well-structured approach to testing the EncodeToBytes method. The table-driven tests cover both successful encoding and error handling scenarios, which is commendable.

To further enhance the test coverage, consider adding the following test cases:

  1. A test case with all fields set to their maximum allowed values.
  2. A test case with the DataFlags field set to various bit combinations.

51-99: Robust test coverage for Header_DecodeFromBytes.

The Test_Header_DecodeFromBytes function demonstrates a comprehensive approach to testing the DecodeFromBytes method. The test cases cover various scenarios, including successful decoding and error handling for invalid inputs.

To further strengthen the test suite, consider adding the following test case:

  • A test case where the input data is exactly 5 bytes long (the minimum valid length) to ensure the function handles edge cases correctly.

101-155: Thorough validation testing for Header_Validate.

The Test_Header_Validate function provides comprehensive coverage for the Validate method of memo.Header. The test cases effectively cover various validation scenarios, ensuring robustness of the validation logic.

To further enhance the test suite, consider adding the following test case:

  • A test case where multiple fields are invalid simultaneously to ensure the validation logic correctly identifies and reports multiple errors.

1-155: Excellent test suite with room for minor enhancements.

The test file header_test.go demonstrates a high-quality, comprehensive approach to testing the memo.Header structure. The consistent use of table-driven tests and the testify/require package contributes to a robust and maintainable test suite.

To further elevate the quality of error handling in tests, consider implementing a helper function for error checking. This function could encapsulate the logic for asserting error messages, reducing duplication and improving readability. For example:

func assertError(t *testing.T, err error, expectedMsg string) {
    t.Helper()
    if expectedMsg == "" {
        require.NoError(t, err)
    } else {
        require.ErrorContains(t, err, expectedMsg)
    }
}

This helper function can then be used in place of the current error checking logic throughout the test file.

go.mod (1)

Line range hint 348-367: Carefully manage forked dependencies.

The use of forked dependencies, particularly for critical components like go-ethereum, go-libp2p, and tss-lib, is noted. While this allows for custom modifications, it also introduces potential challenges:

  1. Maintenance overhead: Keeping forks up-to-date with upstream changes requires ongoing effort.
  2. Divergence risk: Custom modifications may make it difficult to incorporate future upstream improvements.
  3. Community support: Using non-standard forks may limit the ability to leverage community support and resources.

Consider implementing the following strategies:

  1. Document the reasons for each fork and the specific modifications made.
  2. Establish a process for regularly syncing forks with their upstream repositories.
  3. Evaluate the possibility of contributing custom modifications back to the original projects where appropriate.
  4. Set up automated checks to alert when upstream repositories have significant updates or security patches.

This approach will help balance the benefits of customization with the need for long-term maintainability and security.

pkg/memo/codec.go (1)

43-52: Consider handling all encoding formats in GetLenBytes or document limitations.

The GetLenBytes function handles EncodingFmtCompactShort and EncodingFmtCompactLong, but not EncodingFmtABI or EncodingFmtMax. If these formats are intentionally unsupported, consider documenting this limitation. Alternatively, handle all possible encoding formats to enhance the function's robustness.

pkg/memo/memo.go (1)

22-23: Clarify the comment regarding 'RevertGasLimit'

The note at lines 22-23 mentions that 'RevertGasLimit' is not used for non-EVM chains, but this field is not present in the InboundMemo struct. This could be confusing to readers.

Consider updating or removing the comment to reflect the current code:

//   - The 'RevertGasLimit' field is not applicable for non-EVM chains.

Or remove the note if it's no longer relevant.

pkg/memo/codec_abi.go (1)

28-34: Improve field naming for clarity in CodecABI

The field names abiTypes and abiArgs may not clearly convey their purpose. Renaming them to inputTypes and inputArgs enhances readability and expresses their intent more precisely.

Apply this diff to rename the fields:

 type CodecABI struct {
 	// inputTypes contains the ABI types of the arguments
-	abiTypes []string
+	inputTypes []string

 	// inputArgs contains the ABI arguments to be packed or unpacked into
-	abiArgs []interface{}
+	inputArgs []interface{}
 }

Update all references to these fields throughout the code accordingly.

pkg/memo/header.go (1)

119-121: Prepare for future versions in Validate.

The validation currently only accepts Version equal to 0. If future versions are anticipated, consider updating the validation logic to accept a range of versions or define a MaxVersion constant.

For example:

-	if h.Version != 0 {
+	const MaxVersion uint8 = 1 // Set to the maximum supported version
+	if h.Version > MaxVersion {

This change allows for smoother transitions to newer versions in the future.

testutil/sample/memo.go (1)

130-131: Unnecessary Allocation of Fixed-Size Slice

In the abiPad32 function, a 32-byte slice is allocated unconditionally:

padded := make([]byte, 32)

If memo.ABIAlignment is less than 32, this may lead to wasted memory. Consider allocating based on the alignment size:

padded := make([]byte, memo.ABIAlignment)

Ensure that memo.ABIAlignment accurately reflects the intended padding size.

pkg/memo/fields_v0.go (3)

77-80: Revise error message for clarity in Validate method

The error message "payload is not allowed for deposit operation" might be unclear to users. Consider rephrasing it to "payload must be empty for deposit operations" to provide clearer guidance.

Apply this diff to update the error message:

 	if opCode == OpCodeDeposit && len(f.Payload) > 0 {
-		return errors.New("payload is not allowed for deposit operation")
+		return errors.New("payload must be empty for deposit operations")
 	}

126-129: Review error handling for codec.PackArguments

The comment indicates that an error from codec.PackArguments() "never happens." If this error is truly impossible, consider removing the error check to simplify the code. Alternatively, if the error can occur, ensure that it is properly handled and documented.

Apply this diff to adjust the error handling:

 	data, err := codec.PackArguments()
-	if err != nil { // never happens
+	if err != nil {
 		return 0, nil, errors.Wrap(err, "failed to pack arguments")
 	}

28-37: Add documentation comments for exported type FieldsV0

For better code readability and to comply with Go documentation conventions, consider adding a detailed comment for the exported FieldsV0 struct explaining its purpose and usage.

Apply this diff to add the documentation:

 // FieldsV0 contains the data fields of the inbound memo V0
+//
+// It encapsulates the receiver address, optional payload, and revert options
+// used in the memo encoding and decoding processes.
 type FieldsV0 struct {
pkg/memo/codec_abi_test.go (1)

89-95: Ensure error messages in tests are specific and informative

In the test cases where errors are expected, the error messages checked are generic (e.g., "failed to parse ABI string"). To improve test reliability and debuggability, consider making the error messages more specific or matching the exact error returned.

Also applies to: 178-185

pkg/memo/memo_test.go (2)

18-125: Enhance test coverage by including edge cases and optional fields

While the current test cases effectively cover standard scenarios and certain error conditions, consider adding test cases for edge cases and scenarios where optional fields are omitted or set to zero values. This will ensure that the EncodeToBytes function behaves correctly under all possible input conditions.


147-250: Enhance test coverage by including additional edge cases

In the Test_Memo_DecodeFromBytes function, adding test cases for situations where:

  • The data flags indicate no optional fields are set.
  • The input data contains unexpected or malformed values.
  • Only mandatory fields are present.

will improve the robustness of the decoding logic and ensure it handles all possible variations gracefully.

pkg/memo/codec_compact.go (1)

105-106: Improve the clarity of the error message when consumed bytes do not match total bytes.

The current error message could be more informative to aid in debugging mismatches between consumed and total bytes.

Suggested change:

 if offset != len(data) {
-	return fmt.Errorf("consumed bytes (%d) != total bytes (%d)", offset, len(data))
+	return fmt.Errorf("after unpacking, consumed %d bytes but total data length is %d bytes", offset, len(data))
 }
 return nil
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 81fc485 and ed34ac4.

📒 Files selected for processing (20)
  • changelog.md (1 hunks)
  • go.mod (1 hunks)
  • pkg/math/bits.go (1 hunks)
  • pkg/math/bits_test.go (1 hunks)
  • pkg/memo/arg.go (1 hunks)
  • pkg/memo/arg_test.go (1 hunks)
  • pkg/memo/codec.go (1 hunks)
  • pkg/memo/codec_abi.go (1 hunks)
  • pkg/memo/codec_abi_test.go (1 hunks)
  • pkg/memo/codec_compact.go (1 hunks)
  • pkg/memo/codec_compact_test.go (1 hunks)
  • pkg/memo/codec_test.go (1 hunks)
  • pkg/memo/fields.go (1 hunks)
  • pkg/memo/fields_v0.go (1 hunks)
  • pkg/memo/fields_v0_test.go (1 hunks)
  • pkg/memo/header.go (1 hunks)
  • pkg/memo/header_test.go (1 hunks)
  • pkg/memo/memo.go (1 hunks)
  • pkg/memo/memo_test.go (1 hunks)
  • testutil/sample/memo.go (1 hunks)
🧰 Additional context used
📓 Path-based instructions (18)
pkg/math/bits.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

pkg/math/bits_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

pkg/memo/arg.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

pkg/memo/arg_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

pkg/memo/codec.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

pkg/memo/codec_abi.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

pkg/memo/codec_abi_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

pkg/memo/codec_compact.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

pkg/memo/codec_compact_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

pkg/memo/codec_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

pkg/memo/fields.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

pkg/memo/fields_v0.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

pkg/memo/fields_v0_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

pkg/memo/header.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

pkg/memo/header_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

pkg/memo/memo.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

pkg/memo/memo_test.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

testutil/sample/memo.go (1)

Pattern **/*.go: Review the Go code, point out issues relative to principles of clean code, expressiveness, and performance.

🔇 Additional comments (20)
pkg/memo/fields.go (1)

1-13: Approve the Fields interface implementation.

The Fields interface provides a well-structured and comprehensive set of methods for handling memo operations. The interface design is clean, with clear method signatures that cover the essential operations: packing (encoding), unpacking (decoding), and validation.

The use of uint8 for operation codes and encoding formats is appropriate, allowing for efficient representation of these values. The error returns in all methods provide a good mechanism for error handling and reporting.

Overall, this interface forms a solid foundation for implementing memo field operations in the system. The suggested documentation improvements will further enhance its usability and maintainability.

pkg/memo/arg.go (2)

1-2: Package declaration is appropriate.

The package name "memo" accurately reflects the purpose of the code within this file.


20-27: NewArg function is well-implemented.

The NewArg function serves as a clear and concise constructor for CodecArg. It properly initializes all fields and follows Go's idiomatic approach for struct creation.

pkg/math/bits.go (2)

1-5: Package declaration and imports are appropriate.

The package name 'math' is suitable for the bit manipulation functions provided. The import of 'math/bits' is correctly utilized within the file for efficient bit operations.


1-52: Overall, the pkg/math/bits.go file is well-implemented and provides efficient bit manipulation functions.

The functions are logically structured, use efficient bitwise operations, and handle edge cases appropriately. The use of the math/bits package for trailing zero calculations is commendable. Minor suggestions for improvements have been provided to enhance consistency and clarity across the functions.

Consider implementing the suggested changes to further refine this already solid implementation.

pkg/memo/arg_test.go (1)

1-9: Package declaration and imports are appropriate.

The package name memo_test follows Go conventions for external test packages. All imports are necessary and relevant for the test implementation.

pkg/memo/codec_test.go (2)

3-8: Import statements are appropriate and follow best practices.

The use of the testify/require package is commendable, as it enhances test readability and provides clear failure messages.


1-92: Overall, the test file is well-structured and comprehensive.

The use of table-driven tests for both GetLenBytes and GetCodec functions is commendable, allowing for easy expansion of test cases. The tests cover various scenarios, including error cases, which is crucial for robust testing.

To further improve the file:

  1. Consider extracting test cases into separate variables or functions for both tests.
  2. Enhance the Test_GetCodec function with more specific assertions on the returned codec types.
  3. Ensure consistent naming conventions across the project (e.g., Test_GetLenBytes vs TestGetLenBytes).

These minor enhancements will contribute to even more maintainable and comprehensive tests.

pkg/math/bits_test.go (2)

87-132: Comprehensive and well-structured test cases for GetBits function.

The TestGetBits function demonstrates excellent test coverage with a wide range of scenarios, including crucial edge cases. The consistent use of table-driven tests and descriptive names enhances code readability and maintainability.


1-171: Excellent test suite for bit manipulation functions.

The bits_test.go file presents a comprehensive and well-structured test suite for the bit manipulation functions. The consistent use of table-driven tests, descriptive test names, and coverage of edge cases demonstrates a high standard of testing practices.

While some minor suggestions were made to further enhance the test coverage, the overall quality of the test suite is commendable. It provides a solid foundation for ensuring the reliability and correctness of the bit manipulation functions in the math package.

go.mod (1)

337-338: Dependency updates approved.

The updates to github.com/bnb-chain/tss-lib, github.com/showa-93/go-mask, and github.com/tonkeeper/tongo appear to be routine maintenance, keeping these dependencies up-to-date. This is a good practice for security and performance reasons.

Also applies to: 340-341

changelog.md (6)

Line range hint 1-24: Version v12.2.4 focuses on critical fixes and improvements.

The changes in this version primarily address various issues and optimizations:

  1. Enhanced external chain height verification.
  2. Improved gas price calculation for EIP1559 compatibility.
  3. Modified authorization for WhitelistERC20 from group1 to group2.
  4. Refined handling of pending outbound transaction hashes.
  5. Optimized Bitcoin keysign scheduling to prevent failures.
  6. Added support for skipping Goerli BlobTxType transactions.
  7. Improved Bitcoin gas fee calculation using estimated SegWit transaction size.

These fixes demonstrate a focus on improving reliability and compatibility across different blockchain networks. However, it's important to ensure that these changes have been thoroughly tested, especially the modifications to gas price calculations and transaction handling.


Line range hint 87-201: Version v12.0.0 introduces major breaking changes and restructuring.

This version includes significant modifications that will require careful attention during upgrade:

  1. Relocation of TSS and chain validation queries from crosschain to observer module.
  2. Unification of observer sets across all chains.
  3. Merging of observer params and core params into chain params.
  4. Changes to the GetTssAddress query, now requiring Bitcoin chain ID.

These changes represent a substantial restructuring of the system's architecture, particularly in how observers and chain parameters are managed. This could significantly impact existing integrations and workflows.

Recommendations for a smooth transition:

  1. Update all client applications to use the new query endpoints and structures.
  2. Review and update any code that relies on chain-specific observer sets.
  3. Modify any logic that depends on separate observer and core parameters.
  4. Update Bitcoin-related functionality to provide the correct chain ID when querying TSS addresses.
  5. Conduct thorough testing of all affected components in a staging environment before deploying to production.

Additionally, this version introduces several new features and fixes that enhance the system's functionality and reliability. Notable additions include support for snapshots, dynamic gas pricing on zetachain, and new metrics for tracking hotkey burn rates.

To verify the impact of these changes and ensure a smooth transition, please run the following script:

#!/bin/bash
# Description: Verify the impact of breaking changes in v12.0.0

# Check for usage of old query endpoints
rg --type go -A 5 '/zeta-chain/crosschain/'

# Look for any remaining references to chain-specific observer sets
rg --type go -A 5 'ObserversByChain|AllObserverMappers'

# Check for usage of old parameter structures
rg --type go -A 5 'GetCoreParams|GetCoreParamsByChain'

# Verify Bitcoin-related TSS address queries
rg --type go -A 5 'GetTssAddress'

Line range hint 203-233: Version v11.0.0 enhances security and monitoring capabilities.

Key changes in this version:

  1. Added HSM (Hardware Security Module) capability for zetaclient hot key (line 206).
  2. Introduced a new thread to check zeta supply in all connected chains in every block (lines 207-208).
  3. Added a new transaction to update an observer (line 209).
  4. Various fixes, including improvements to gas and asset token contract redeployment, and Bitcoin-related issues.

The addition of HSM support for the zetaclient hot key is a significant security enhancement that should help protect sensitive key material. The new thread for checking zeta supply provides improved monitoring capabilities, which can help maintain the integrity of the system.

Suggestions for follow-up:

  1. Conduct a security audit of the HSM integration to ensure it meets best practices.
  2. Develop and document procedures for key management using the new HSM capability.
  3. Monitor the performance impact of the new zeta supply checking thread, especially on networks with many connected chains.
  4. Create alerts based on the zeta supply checks to quickly identify any discrepancies.

To verify the implementation and impact of these changes, please run the following script:

#!/bin/bash
# Description: Verify HSM integration and zeta supply checking

# Check for HSM-related code
rg --type go -A 5 'HSM|Hardware.?Security.?Module'

# Look for the new zeta supply checking thread
rg --type go -A 10 'check.?zeta.?supply'

# Verify the new observer update transaction
rg --type go -A 5 'update.?observer'

Line range hint 235-321: Version v10.1.2 introduces significant features and fixes.

Key changes in this version:

  1. Added external stress testing capability (line 238).
  2. Implemented liquidity cap setting for ZRC20 (line 239).
  3. Added Bitcoin block header and merkle proof functionality (line 241).
  4. Introduced TSS funds migration capability (line 244).
  5. Various fixes and improvements, including gas stability pool balance queries and authorization checks.

These changes represent significant enhancements to the system's functionality and reliability. The addition of external stress testing should improve the robustness of the system, while the liquidity cap for ZRC20 provides better control over token economics. The Bitcoin-related changes enhance the system's interoperability with the Bitcoin network.

Suggestions for follow-up:

  1. Develop a comprehensive stress testing plan utilizing the new external stress testing capability.
  2. Create guidelines for setting appropriate liquidity caps for ZRC20 tokens.
  3. Thoroughly test the Bitcoin block header and merkle proof functionality to ensure accuracy and performance.
  4. Document the TSS funds migration process and create recovery procedures.
  5. Monitor the gas stability pool balances and adjust parameters if necessary.

To verify the implementation and impact of these changes, please run the following script:

#!/bin/bash
# Description: Verify new features and fixes in v10.1.2

# Check for stress testing related code
rg --type go -A 5 'stress.?test'

# Look for ZRC20 liquidity cap implementation
rg --type go -A 10 'ZRC20|liquidity.?cap'

# Verify Bitcoin block header and merkle proof functionality
rg --type go -A 10 'Bitcoin.?(block.?header|merkle.?proof)'

# Check TSS funds migration implementation
rg --type go -A 10 'TSS.?funds.?migration'

# Look for gas stability pool balance query
rg --type go -A 5 'gas.?stability.?pool.?balance'

Line range hint 323-441: Versions v13.0.0 to v15.0.0 introduce important security enhancements and functionality improvements.

Key changes across these versions:

  1. Added password prompts for hotkey and TSS key-share in zetaclient (v13.0.0, line 328-329).
  2. Implemented Bitcoin dynamic depositor fee (v13.0.0, line 333).
  3. Added support for refunding aborted transactions by minting tokens to zEVM (v13.0.0, line 337).
  4. Introduced a reset chain nonces message (v15.0.0, line 427).

These changes represent significant improvements in security and functionality, particularly in relation to key management and Bitcoin integration. The addition of password prompts for sensitive keys enhances the overall security of the system, while the Bitcoin dynamic depositor fee improves the flexibility of Bitcoin transactions.

Suggestions for follow-up:

  1. Develop clear documentation and user guides for the new password prompt system in zetaclient.
  2. Conduct thorough testing of the Bitcoin dynamic depositor fee mechanism under various network conditions.
  3. Create monitoring and alerting systems for aborted transactions that are refunded to zEVM.
  4. Establish guidelines and procedures for using the new reset chain nonces message, including potential security implications.

To verify the implementation and impact of these changes, please run the following script:

#!/bin/bash
# Description: Verify key changes in versions v13.0.0 to v15.0.0

# Check for password prompt implementation in zetaclient
rg --type go -A 10 'password.?prompt|hotkey.?password|tss.?keyshare.?password'

# Look for Bitcoin dynamic depositor fee implementation
rg --type go -A 10 'Bitcoin.?dynamic.?depositor.?fee'

# Verify aborted transaction refund mechanism
rg --type go -A 10 'aborted.?transaction|refund.?to.?zEVM'

# Check reset chain nonces message implementation
rg --type go -A 10 'reset.?chain.?nonces'

Line range hint 26-85: Version v12.1.0 introduces important features and fixes.

Key changes in this version:

  1. Modified emission distribution to use fixed block rewards (line 60).
  2. Added chain header tests in E2E tests (line 55).
  3. Several fixes addressing issues with ballot voting, chain params comparison, and gas price checks.
  4. Refactoring of zetaclient into subpackages (line 81).

The modification of emission distribution to use fixed block rewards is a significant change that could impact the network's economics. It's crucial to ensure that this change has been thoroughly analyzed for its long-term effects on the network's incentive structure.

Suggestions for follow-up:

  1. Conduct a comprehensive economic analysis of the new emission distribution model.
  2. Ensure that all stakeholders are informed about this change and its potential impacts.
  3. Monitor the network closely after implementation to verify that the new model behaves as expected.

To verify the impact of the emission distribution change, please run the following script:

pkg/memo/codec.go (1)

1-64: Overall code structure is clear and follows good practices.

The code is well-structured with a clear separation of concerns. Constants and interfaces are appropriately defined, and the use of encoding formats is well-organized.

pkg/memo/header.go (1)

71-74: Verify correct bit manipulation in EncodeToBytes.

Ensure that the SetBits function correctly sets the bits for Version, EncodingFormat, OpCode, and Reserved in ctrlByte1 and ctrlByte2. Misalignment or overlap in bit positions due to incorrect masks could lead to improper encoding of the header.

Consider reviewing the masks and their application to confirm they align with the intended bit positions.

Also applies to: 77-80

pkg/memo/fields_v0.go (1)

47-50: Consistent error wrapping for codec retrieval

In both Pack and Unpack methods, errors from GetCodec are wrapped with additional context. Ensure that this practice is consistent across the codebase for better error traceability.

pkg/memo/arg.go Show resolved Hide resolved
pkg/memo/arg.go Show resolved Hide resolved
pkg/memo/arg.go Show resolved Hide resolved
go.mod Outdated Show resolved Hide resolved
pkg/memo/codec.go Show resolved Hide resolved
pkg/memo/codec_compact.go Show resolved Hide resolved
pkg/memo/fields_v0_test.go Outdated Show resolved Hide resolved
pkg/memo/fields_v0_test.go Outdated Show resolved Hide resolved
pkg/memo/fields_v0_test.go Show resolved Hide resolved
pkg/memo/codec_compact_test.go Outdated Show resolved Hide resolved
Copy link

!!!WARNING!!!
nosec detected in the following files: pkg/memo/codec_compact.go

Be very careful about using #nosec in code. It can be a quick way to suppress security warnings and move forward with development, it should be employed with caution. Suppressing warnings with #nosec can hide potentially serious vulnerabilities. Only use #nosec when you're absolutely certain that the security issue is either a false positive or has been mitigated in another way.

Only suppress a single rule (or a specific set of rules) within a section of code, while continuing to scan for other problems. To do this, you can list the rule(s) to be suppressed within the #nosec annotation, e.g: /* #nosec G401 */ or //#nosec G201 G202 G203
Broad #nosec annotations should be avoided, as they can hide other vulnerabilities. The CI will block you from merging this PR until you remove #nosec annotations that do not target specific rules.

Pay extra attention to the way #nosec is being used in the files listed above.

@github-actions github-actions bot added the nosec label Oct 10, 2024
Copy link
Member

@lumtis lumtis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, good that we have everything isolated in a package.

I'm wondering if we could consider having in this package the legacy parsing, getting the address and calldata from a memo using the old way with Bitcoin?

pkg/memo/codec_compact.go Show resolved Hide resolved
pkg/memo/memo_test.go Show resolved Hide resolved
Copy link
Contributor

@swift1337 swift1337 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solid work 👍

pkg/math/bits.go Outdated Show resolved Hide resolved
pkg/math/bits.go Outdated Show resolved Hide resolved
pkg/memo/memo.go Show resolved Hide resolved
pkg/memo/memo.go Show resolved Hide resolved
pkg/memo/memo.go Outdated Show resolved Hide resolved
pkg/memo/memo_test.go Show resolved Hide resolved
pkg/memo/header.go Outdated Show resolved Hide resolved
pkg/memo/header.go Outdated Show resolved Hide resolved
pkg/memo/memo_test.go Show resolved Hide resolved
@ws4charlie
Copy link
Contributor Author

ws4charlie commented Oct 15, 2024

Looks great, good that we have everything isolated in a package.

I'm wondering if we could consider having in this package the legacy parsing, getting the address and calldata from a memo using the old way with Bitcoin?

Yes, if you meat moving func ParseAddressAndData(message string) (ethcommon.Address, []byte, error) to the memo package. Here is the commit 798f566

Copy link
Member

@lumtis lumtis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me for initialization, tests will be either to visualize once we have actual E2E tests

Copy link
Contributor

@swift1337 swift1337 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. The only topic left is to agree on the terminology

@ws4charlie ws4charlie added this pull request to the merge queue Oct 16, 2024
Merged via the queue into develop with commit 250b90e Oct 16, 2024
35 checks passed
@ws4charlie ws4charlie deleted the feat-inbound-memo branch October 16, 2024 16:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants