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

main<-dev: refactor callback functions and improve timedSignature #60

Open
wants to merge 105 commits into
base: main
Choose a base branch
from

Conversation

foxytanuki
Copy link
Member

@foxytanuki foxytanuki commented Oct 22, 2024

Includes:

Summary by CodeRabbit

Release Notes

  • New Features

    • Support for the Sepolia Testnet added, including updated documentation and token acquisition instructions.
    • New API methods for nonce retrieval and enhanced signature generation with nonce and target function hash.
    • Introduction of a Function Hash Generator utility for generating Keccak256 hashes for Solidity function signatures.
    • New shell script for generating Go bindings from Solidity smart contracts.
    • Enhanced functionality for managing account approvals and nonce handling in the smart contract.
    • New configuration file for YAML language server settings.
    • Improved instructions for testing in a local environment.
  • Bug Fixes

    • Improved error handling across various components, ensuring clearer feedback during failures.
  • Documentation

    • Comprehensive updates to the README and API documentation to reflect new features and usage instructions.
    • New documentation for the Function Hash Generator utility.
    • Updates to the "How to test on Local Environment" section.
  • Refactor

    • Enhanced server architecture for better interaction with Ethereum smart contracts.
    • Updated test structures to align with new functionality and improve modularity.
  • Chores

    • Modifications to CI workflow triggers and .gitignore for better project management.

foxytanuki and others added 15 commits October 18, 2024 15:18
Co-authored-by: foxytanuki <45069709+foxytanuki@users.noreply.github.com>
* Update README.md (#45)

separeted input and output about Generate signatures

* update CreateAccountResponse

* update AccountCreated event catch error

* add error about missing public key

* remove go in root

* rename a field of CreateAccountResponse

* update transferable_account.pb.go with merging dev

* update for SignatureAlgorithm

* add test for CreateAccountResponse field

* remove a comment

---------

Co-authored-by: yosui <35430745+yosui@users.noreply.github.com>
* update test-go

* update generate_timed_signature scripts

* add InvalidTargetFunctionHash

* add godotenv to server.go

* update generate_timed_signature script for new TimedSignature

* to avoid hardcoding constansts

* add privateKey params for generate_timed_signature script
Copy link

coderabbitai bot commented Nov 1, 2024

Walkthrough

The pull request includes several updates across multiple files, primarily focusing on enhancing the functionality and documentation of the Astraeus project. Key changes involve modifying environment variables, updating CI workflow triggers, enhancing Solidity contract management, and refining API documentation. New features include nonce handling for signatures, improved error handling, and the introduction of new utility functions for generating timed signatures. Additionally, several tests have been updated to reflect these changes, ensuring comprehensive coverage of the new functionalities.

Changes

File Change Summary
.env.example Updated TA_STORE_CONTRACT_ADDRESS from 0x8F7B5945D5213575b0fAdF876701b79B359c977b to 0xEa8a6ce7098B79Bd8B4920120734a5081046C44F.
.github/workflows/ci.yaml Modified CI workflow triggers to include dev branch alongside main.
.gitignore Added entries for cache/, out/, .DS_Store, and .env; removed entry for go.
Makefile Updated Docker Compose file references; added build-solidity-extra and gen-solidity-go-bindings targets; modified test-go and test-e2e-docker targets.
README.md Added support for Sepolia Testnet; updated instructions for generating signatures and account management.
docs/api.md Added GetNonceRequest and GetNonceResponse; updated Account struct and function signatures.
scripts/e2e/main.go Updated imports and function signatures to use ct.SignatureVerifierTimedSignature.
scripts/e2e/send_tx/main.go Introduced framework and impl packages; updated signature generation logic.
scripts/utils/execute_withdraw_tx/main.go Adjusted command-line arguments to include private key; updated error handling.
scripts/utils/gen-solidity-go-bindings.sh New script for generating Go bindings for Solidity contracts.
scripts/utils/generate_function_hash/README.md New README for Function Hash Generator utility.
scripts/utils/generate_function_hash/main.go New command-line utility for computing Keccak-256 hashes.
scripts/utils/generate_timed_signature/main.go Removed old signature generation logic; introduced new structured approach.
src/go/server/constants.go Added constants for function hashes related to account management.
src/go/server/server.go Enhanced server functionality; added GetNonce method and improved error handling.
src/go/server/server_test.go Refactored tests to align with new server structure and signature generation logic.
src/proto/api/v1/transferable_account.proto Updated account structure and added GetNonce RPC method.
src/solidity/TransferableAccountStore.sol Introduced nonce handling; refactored functions for account management.
src/solidity/interfaces/ITransferableAccountStore.sol Updated account struct and function signatures for signature verification.
src/solidity/lib/SignatureVerifier.sol Modified TimedSignature struct and updated signature verification logic.
test/TransferableAccountStore.t.sol Updated tests to reflect new signature generation logic and function hashes.
test/e2e/e2e_test.go Enhanced end-to-end tests for account management; updated signature generation methods.
test/integration/auth_test.go Updated signature generation in tests to align with new functionality.
test/utils/constants.go Adjusted alignment of HostURL constant assignment.
test/utils/helpers.go Updated helper functions to include contract interactions in signature generation.
test/utils/server.go Added GetNonce function for retrieving nonces in tests.
test/utils/sign.go Introduced new functions for account creation and signature generation; removed old signature method.
.coderabbit.yaml New configuration file created for YAML language server settings.

Possibly related PRs

  • update CreateAccountResponse #56: The changes in the CreateAccountResponse structure and the CreateAccount method in server.go are related to the main PR as they both involve updates to the handling of account-related functionalities, specifically in how account addresses are managed and returned.
  • dev: update by coderabbit #73: This PR modifies the TransferableAccountStore contract, which is directly related to the changes in the main PR regarding the TA_STORE_CONTRACT_ADDRESS, as it affects how accounts are managed and signatures are verified in the contract.
  • dev: Add docs how to test on local environment #74: The documentation update on how to test in a local environment includes instructions for setting up the .env file, which directly relates to the changes made in the main PR regarding the TA_STORE_CONTRACT_ADDRESS.

Suggested reviewers

  • foxytanuki

🐰 In the land of code, where changes bloom,
New signatures dance, dispelling the gloom.
With nonces and hashes, our project takes flight,
In the world of Ethereum, we shine ever bright!
So hop along, friends, let’s test and deploy,
For every new feature brings us such joy! 🌟


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.

* rename TransferAccountRequest param from to to address

* fmt constants.go
* update test-go

* update generate_timed_signature scripts

* add InvalidTargetFunctionHash

* add godotenv to server.go

* update generate_timed_signature script for new TimedSignature

* to avoid hardcoding constansts

* add privateKey params for generate_timed_signature script

* update prerequisites about sepolia accounts

* update .env.example for TA_STORE_CONTRACT_ADDRESS on toliman

* update Getting Started about Create Account

* add examples for CreateAccount

* update GettingStarted about ApproveAddress

* update GettingStarted about TransferAccount

* update README about Deposit SepoliaETH

* Revert "add godotenv to server.go"

This reverts commit f2a451d.

* update GettingStarted about UnlockAccount

* rename TransferAccountRequest param from to to address

* fmt constants.go

* update execute-withdraw-tx script

* update GettingStarted for Sign

* add testSignAfterTransfer
Copy link

@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: 55

🧹 Outside diff range and nitpick comments (32)
scripts/utils/generate_function_hash/main.go (1)

1-27: Consider enhancing utility features.

The current implementation serves its basic purpose well, but consider these enhancements for better integration with smart contract development workflows:

  1. Add support for processing multiple function signatures from a file
  2. Add flags for different output formats (hex with/without 0x, bytes, uint)
  3. Add support for parsing ABI files directly to extract function signatures

Would you like me to provide implementation details for any of these suggestions?

src/go/server/constants.go (1)

3-24: Consider enhancing the documentation.

While the comments show function signatures, it would be helpful to add:

  1. A package-level comment explaining the purpose of these constants
  2. Brief descriptions of what each function does
  3. Example usage in code

Here's a suggested improvement for the documentation:

 package server
+
+// Function hashes used for signature verification in account management operations.
+// These hashes are used to verify TimedSignatures for various account-related actions
+// such as approval, creation, transfer, deletion, and signing.
 
 const (
-       // ApproveAddress(SignatureVerifier.TimedSignature timedSignature,string accountId,address _address)
+       // APPROVE_ADDRESS_FUNCTION_HASH is used when approving an address for account access
+       // Function: ApproveAddress(SignatureVerifier.TimedSignature timedSignature,string accountId,address _address)
        APPROVE_ADDRESS_FUNCTION_HASH = "0x16d1dabab53b460506870428d7a255f9bff53294080a73797c114f4e25b5e76f"
.github/workflows/ci.yaml (1)

Line range hint 46-47: Tests are currently disabled in CI.

The test section is commented out, which means the CI pipeline is not executing any tests. This is concerning, especially for a PR that involves refactoring callback functions and improving functionality. Consider re-enabling tests to ensure the changes don't introduce regressions.

Apply this diff to re-enable tests:

-      # - name: Test
-      #   run: make test
+      - name: Test
+        run: make test
Makefile (1)

44-44: Consider the performance impact of disabling test caching.

Adding -count=1 ensures fresh test runs by bypassing the test cache. While this is good for testing callback functions and signatures that might have timing dependencies, it could increase CI execution time.

Consider making this configurable or documenting why test caching is disabled.

scripts/e2e/main.go (2)

Line range hint 110-121: Consider security and error handling improvements.

  1. The function logs the entire proof data which might include sensitive information. Consider logging only non-sensitive fields or masking sensitive data.
  2. The hex conversions using fmt.Sprintf("%x", ...) don't have error handling. While unlikely to fail with valid signature data, consider using hexutil package for more robust handling.

Here's a suggested improvement:

 func createAccount(timedSignature ct.SignatureVerifierTimedSignature) {
     url := fmt.Sprintf("%s/v1/accounts", hostURL)
     data := map[string]interface{}{
         "proof": map[string]interface{}{
             "validFor":    timedSignature.ValidFor,
             "messageHash": fmt.Sprintf("%x", timedSignature.MessageHash),
             "signature":   fmt.Sprintf("%x", timedSignature.Signature),
             "signer":      timedSignature.Signer.Hex(),
         },
     }
-    log.Printf("Creating account with: %v", data)
+    log.Printf("Creating account for signer: %s", timedSignature.Signer.Hex())
     sendRequest(url, data)
 }

Line range hint 23-43: Consider enhancing E2E test infrastructure.

The current E2E test setup relies heavily on environment variables and external setup steps. Consider:

  1. Adding a test configuration file to manage test parameters
  2. Implementing automated setup/teardown of the SUAVE server for CI/CD
  3. Adding retry mechanisms for API calls to handle network flakiness

Would you like assistance in implementing any of these improvements?

src/proto/api/v1/transferable_account.proto (1)

31-32: Add detailed field documentation.

While the additions enhance security, please add detailed comments explaining:

  • The purpose and format of the nonce (e.g., monotonically increasing counter)
  • The derivation method for target_function_hash (e.g., keccak256 of function signature)
-    uint64 nonce = 5;
-    string target_function_hash = 6; // hex encoded
+    // Monotonically increasing counter to prevent replay attacks
+    uint64 nonce = 5;
+    // Keccak256 hash of the target function signature (hex encoded)
+    string target_function_hash = 6;
docs/api.md (4)

17-18: Fix list indentation in Table of Contents.

The indentation level for these entries should be 2 spaces to match the rest of the list items.

-    - [GetNonceRequest](#api-v1-GetNonceRequest)
-    - [GetNonceResponse](#api-v1-GetNonceResponse)
+  - [GetNonceRequest](#api-v1-GetNonceRequest)
+  - [GetNonceResponse](#api-v1-GetNonceResponse)
🧰 Tools
🪛 Markdownlint

17-17: Expected: 2; Actual: 4
Unordered list indentation

(MD007, ul-indent)


18-18: Expected: 2; Actual: 4
Unordered list indentation

(MD007, ul-indent)


210-239: Clean up documentation formatting for GetNonce types.

Remove excessive blank lines to maintain consistent formatting with other type definitions.

 <a name="api-v1-GetNonceRequest"></a>
-
 ### GetNonceRequest
-
-
-
 | Field | Type | Label | Description |
 | ----- | ---- | ----- | ----------- |
 | address | [string](#string) |  |  |
-
-
-
-
-
-
 <a name="api-v1-GetNonceResponse"></a>
-
 ### GetNonceResponse
-
-
-
 | Field | Type | Label | Description |
 | ----- | ---- | ----- | ----------- |
 | nonce | [uint64](#uint64) |  |  |
-
-
-
-
-

422-423: Enhance documentation for new TimedSignature fields.

The new fields nonce and target_function_hash would benefit from additional documentation explaining:

  • Purpose and usage of the nonce
  • Format and generation of the target function hash
  • Impact on signature validation
-| nonce | [uint64](#uint64) |  |  |
-| target_function_hash | [string](#string) |  | hex encoded |
+| nonce | [uint64](#uint64) |  | Unique number to prevent replay attacks |
+| target_function_hash | [string](#string) |  | Hex encoded hash of the target function to prevent function call injection |

493-502: Improve SignatureAlgorithm enum documentation and formatting.

  1. Fix indentation to match other sections
  2. Add descriptive documentation for each enum value
 <a name="api-v1-SignatureAlgorithm"></a>
-
 ### SignatureAlgorithm
 | Name | Number | Description |
 | ---- | ------ | ----------- |
-| SignatureAlgorithm_UNSPECIFIED | 0 |  |
-| SignatureAlgorithm_ECDSA | 1 |  |
-| SignatureAlgorithm_EDDSA | 2 |  |
+| SignatureAlgorithm_UNSPECIFIED | 0 | Default value, invalid |
+| SignatureAlgorithm_ECDSA | 1 | Elliptic Curve Digital Signature Algorithm |
+| SignatureAlgorithm_EDDSA | 2 | Edwards-curve Digital Signature Algorithm |
README.md (4)

40-42: Add specific token amount requirements to prerequisites.

Consider specifying the minimum amount of TEETH and SepoliaETH tokens required for the operations to help users prepare adequately.


64-84: Add language specifiers to code blocks and improve command explanation.

The code blocks should specify their language for better syntax highlighting and readability.

Apply these improvements:

-   ```
+   ```bash
    go run scripts/utils/generate_timed_signature/main.go <your_private_key> CreateAccount
    ```

-   ```
+   ```bash
    go run scripts/utils/generate_timed_signature/main.go 10c62a6364b1730ec101460c871952403631adb66fe7e043914c7d0056ca8e94 CreateAccount
    ```

-   ```
+   ```json
    "proof": {
      "validFor": 1730260787,
      ...
    }
    ```
🧰 Tools
🪛 Markdownlint

64-64: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


71-71: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


76-76: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


283-285: Add warning about gas fees for unlock operation.

The unlock operation section should mention potential gas fees and recommend having sufficient tokens for the transaction.

Add the following note:

   After the transfer of the TA is complete, let's perform the unlock operation from the account that received the TA.
   By unlocking the TA, you will be able to withdraw assets from addresses on different chains associated with the TA.
+   Note: This operation requires gas fees. Ensure you have sufficient TEETH tokens in your account before proceeding.

360-361: Enhance transaction confirmation warning.

The transaction confirmation section should include more detailed warnings about transaction irreversibility and double-checking parameters.

Add the following warning:

   Please note that the private key of the account that received the TA on the Toliman Testnet will be required.
+   WARNING: Cryptocurrency transactions are irreversible. Please double-check all parameters before confirming.

   When the transaction is ready, you will be prompted to confirm whether to proceed, as shown in the example below. If everything looks good, type 'y' and press Enter.
+   Carefully verify the recipient address and amount before confirming the transaction.

Also applies to: 366-367

test/integration/auth_test.go (1)

86-86: Unnecessary conversion to []byte in modifiedSignature.

The Signature field in timedSignature is already of type []byte. Casting it again using []byte is redundant.

Apply this diff to remove the unnecessary conversion:

-			modifiedSignature := tc.modifySig([]byte(timedSignature.Signature))
+			modifiedSignature := tc.modifySig(timedSignature.Signature)
test/utils/sign.go (1)

Line range hint 110-112: Verify signature length before modifying.

Modifying signature[64] without ensuring the signature has at least 65 bytes may cause an index out of range error.

Add a length check before adjusting the signature:

+	if len(signature) < 65 {
+		return [32]byte{}, nil, fmt.Errorf("signature length is insufficient")
+	}
	// Adjust the v value of the signature (add 27)
	signature[64] += 27
scripts/e2e/send_tx/main.go (1)

89-89: Make Expiration Duration Configurable

The expiration time for the timed signature is hardcoded to 86400 seconds (1 day). Making this value configurable enhances flexibility and maintainability.

Define a constant for the expiration duration:

+const expirationDurationSeconds = 86400 // 1 day
...
-	timedSignature, err := testutil.NewPbTimedSignature(taStoreContract, privKey, uint64(time.Now().Unix()+86400), common.HexToHash(impl.CREATE_ACCOUNT_FUNCTION_HASH))
+	timedSignature, err := testutil.NewPbTimedSignature(taStoreContract, privKey, uint64(time.Now().Unix()+expirationDurationSeconds), common.HexToHash(impl.CREATE_ACCOUNT_FUNCTION_HASH))
scripts/utils/execute_withdraw_tx/main.go (1)

136-140: Make the timed signature expiry duration configurable.

The expiry time for timed signatures is hardcoded to 24 hours (86400 seconds). Making this value configurable enhances flexibility and allows for easier adjustments without modifying the code.

Apply this diff to define a constant for the expiry duration:

+	const timedSignatureExpiry = 86400 // Expiry duration in seconds (24 hours)

	...

-		timedSignature, err := testutil.NewPbTimedSignature(taStoreContract, privKey, uint64(time.Now().Unix()+86400), common.HexToHash(impl.UNLOCK_ACCOUNT_FUNCTION_HASH))
+		timedSignature, err := testutil.NewPbTimedSignature(taStoreContract, privKey, uint64(time.Now().Unix()+timedSignatureExpiry), common.HexToHash(impl.UNLOCK_ACCOUNT_FUNCTION_HASH))

	...

-		timedSignature, err := testutil.NewPbTimedSignature(taStoreContract, privKey, uint64(time.Now().Unix()+86400), common.HexToHash(impl.SIGN_FUNCTION_HASH))
+		timedSignature, err := testutil.NewPbTimedSignature(taStoreContract, privKey, uint64(time.Now().Unix()+timedSignatureExpiry), common.HexToHash(impl.SIGN_FUNCTION_HASH))

Also applies to: 192-196

src/solidity/TransferableAccountStore.sol (2)

345-359: Consistent use of public vs. external visibility for functions.

The verifyTimedSignature function is marked as public, but it is only called internally. For optimization, consider changing its visibility to internal or private if it's not intended for external use. Similarly, review the visibility of other functions to ensure they are appropriately restricted.

Apply this diff to adjust the visibility:

-function verifyTimedSignature(SignatureVerifier.TimedSignature calldata timedSignature, bytes32 targetFunctionHash)
-    public
+function verifyTimedSignature(SignatureVerifier.TimedSignature calldata timedSignature, bytes32 targetFunctionHash)
+    internal
     view
     returns (bool)
 {

332-337: Consider ordering nonce increment before signature verification.

In the consumeNonce function, the nonce is incremented after verifying the signature. This could potentially allow multiple failed verification attempts to prevent future valid transactions if the nonce is not incremented upon failure. Evaluate whether incrementing the nonce before verification may be more appropriate to prevent such scenarios.

Review and adjust the nonce handling logic if necessary to ensure robustness against repeated invalid attempts.

src/go/server/server.go (3)

Line range hint 368-373: Avoid using panic for error handling

Using panic in production code can cause the server to crash, resulting in downtime.

Replace panic(err) with proper error handling to ensure the server remains robust.

Apply this diff to handle the error gracefully:

	caEvent, err := s.taStoreContract.Abi.Events["Signature"].ParseLog(result.Logs[0])
	if err != nil {
-		panic(err)
+		return nil, fmt.Errorf("failed to parse Signature event: %v", err)
	}

Line range hint 376-398: Leverage contract bindings for type-safe contract calls

Manually handling contract call results and type assertions can lead to errors if the contract interface changes.

Use the generated contract bindings to perform contract calls, ensuring type safety and reducing the risk of runtime errors.

Apply this diff to use contract bindings:

-func (s *server) GetAccount(ctx context.Context, req *pb.GetAccountRequest) (*pb.GetAccountResponse, error) {
-	result := s.taStoreContract.Call("getAccount", []interface{}{req.AccountId})
-
-	if len(result) == 0 || result[0] == nil {
-		return nil, fmt.Errorf("empty result")
-	}
-
-	ac, ok := result[0].(struct {
-		AccountId          [16]uint8      `json:"accountId"`
-		Owner              common.Address `json:"owner"`
-		PublicKeyX         *big.Int       `json:"publicKeyX"`
-		PublicKeyY         *big.Int       `json:"publicKeyY"`
-		SignatureAlgorithm uint8          `json:"signatureAlgorithm"`
-		IsLocked           bool           `json:"isLocked"`
-	})
-	if !ok {
-		return nil, status.Errorf(codes.InvalidArgument, "account data type is invalid or unexpected")
-	}
+func (s *server) GetAccount(ctx context.Context, req *pb.GetAccountRequest) (*pb.GetAccountResponse, error) {
+	ac, err := s.taStoreContractBind.GetAccount(nil, req.AccountId)
+	if err != nil {
+		return nil, fmt.Errorf("failed to get account: %v", err)
+	}

38-39: Improve naming consistency for contract fields

The fields taStoreContract and taStoreContractBind in the server struct can be confusing due to their similar names.

Consider renaming for clarity:

type server struct {
	pb.UnimplementedAccountServiceServer
	fr                  *framework.Framework
-	taStoreContract     *framework.Contract
-	taStoreContractBind *ct.Transferableaccountstore
+	frameworkContract   *framework.Contract
+	contract            *ct.Transferableaccountstore
	auth                *bind.TransactOpts
	client              *ethclient.Client
}
test/e2e/e2e_test.go (2)

Line range hint 214-219: Refactor repeated code for generating delete signatures

The code for generating delete signatures is similar across tests. Consider creating a helper function to generate these signatures, enhancing code readability and maintainability.

Create a helper function like GenerateDeleteSignatureHelper to encapsulate this functionality.


Line range hint 441-450: Correctly generate signatures using the appropriate private key

In the revocation test, the transfer signature is generated using tc.to, which may not be appropriate. Ensure that the correct private key is used based on the test case logic.

Verify if tc.sender should be used instead of tc.to when generating the signature, depending on who is performing the action.

src/go/server/server_test.go (2)

Line range hint 96-109: Enhance test coverage with additional edge cases

Consider adding test cases with invalid but well-formed account IDs to ensure that the GetAccount function handles them correctly.

For example:

{"Malformed account ID", "!nv@l1d_@cc0unt#d", true},

Line range hint 508-534: Clarify assumptions in TestIsAccountLocked

The assumption that a non-existent account returns false for IsAccountLocked might not align with expected behavior. Typically, querying a non-existent account should result in an error.

Consider updating the test case expectations or handling errors appropriately:

-{"Non-existent account", "non_existent_account_id", false, false},
+{"Non-existent account", "non_existent_account_id", true, false},

And update the assertion:

if tc.expectErr {
	assert.Error(t, err)
	assert.Nil(t, resp)
} else {
	// existing assertions
}
test/TransferableAccountStore.t.sol (4)

137-137: Fix typo in assertion message

There is a typo in the assertion message: "Stored account shouold be locked" should be "Stored account should be locked".

Apply this diff:

- assertTrue(isLocked, "Stored account shouold be locked");
+ assertTrue(isLocked, "Stored account should be locked");

266-273: Simplify assertion for comparing enums

When comparing enum values, you can compare them directly without casting to uint256.

Apply this diff to simplify the assertion:

- assertEq(
-     uint256(retrievedAccount.signatureAlgorithm),
-     uint256(decodedAccount.signatureAlgorithm),
-     "signatureAlgorithm should match"
- );
+ assertEq(
+     retrievedAccount.signatureAlgorithm,
+     decodedAccount.signatureAlgorithm,
+     "Signature algorithm should match"
+ );

459-461: Remove redundant require statement after assertTrue

The require statement require(isAccountLocked, "Account should be still locked"); is redundant since you've already used assertTrue(isAccountLocked, "Account should be locked immediately after creation");.

You can remove the redundant require statement to clean up the code.

assertTrue(isAccountLocked, "Account should be locked immediately after creation");

-require(isAccountLocked, "Account should be still locked");

467-470: Handle expected revert with a message

When expecting a revert, it's good practice to specify the expected error message to ensure that the correct revert is being caught.

Modify the expectRevert to include the expected error message:

- vm.expectRevert();
+ vm.expectRevert("Account is locked");
tas.sign(sig_1, accountId, abi.encodePacked(hashedDummyData));
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 243e354 and 0c4d79d.

⛔ Files ignored due to path filters (5)
  • src/go/pb/api/v1/transferable_account.pb.go is excluded by !**/*.pb.go
  • src/go/pb/api/v1/transferable_account.pb.gw.go is excluded by !**/*.pb.gw.go
  • src/go/pb/api/v1/transferable_account_grpc.pb.go is excluded by !**/*.pb.go
  • src/go/pb/google/api/annotations.pb.go is excluded by !**/*.pb.go
  • src/go/pb/google/api/http.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (27)
  • .env.example (1 hunks)
  • .github/workflows/ci.yaml (1 hunks)
  • .gitignore (0 hunks)
  • Makefile (3 hunks)
  • README.md (2 hunks)
  • docs/api.md (9 hunks)
  • scripts/e2e/main.go (3 hunks)
  • scripts/e2e/send_tx/main.go (2 hunks)
  • scripts/utils/execute_withdraw_tx/main.go (5 hunks)
  • scripts/utils/gen-solidity-go-bindings.sh (1 hunks)
  • scripts/utils/generate_function_hash/README.md (1 hunks)
  • scripts/utils/generate_function_hash/main.go (1 hunks)
  • scripts/utils/generate_timed_signature/main.go (1 hunks)
  • src/go/server/constants.go (1 hunks)
  • src/go/server/server.go (10 hunks)
  • src/go/server/server_test.go (22 hunks)
  • src/proto/api/v1/transferable_account.proto (5 hunks)
  • src/solidity/TransferableAccountStore.sol (10 hunks)
  • src/solidity/interfaces/ITransferableAccountStore.sol (2 hunks)
  • src/solidity/lib/SignatureVerifier.sol (1 hunks)
  • test/TransferableAccountStore.t.sol (7 hunks)
  • test/e2e/e2e_test.go (18 hunks)
  • test/integration/auth_test.go (2 hunks)
  • test/utils/contants.go (1 hunks)
  • test/utils/helpers.go (3 hunks)
  • test/utils/server.go (1 hunks)
  • test/utils/sign.go (1 hunks)
💤 Files with no reviewable changes (1)
  • .gitignore
✅ Files skipped from review due to trivial changes (3)
  • .env.example
  • scripts/utils/gen-solidity-go-bindings.sh
  • test/utils/contants.go
🧰 Additional context used
🪛 Markdownlint
README.md

363-363: null
Dollar signs used before commands without showing output

(MD014, commands-show-output)


64-64: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


71-71: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


76-76: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


91-91: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


105-105: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


119-119: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


139-139: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


144-144: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


149-149: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


163-163: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


181-181: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


199-199: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


212-212: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


217-217: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


222-222: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


236-236: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


254-254: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


272-272: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


289-289: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


294-294: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


299-299: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


313-313: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


330-330: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


347-347: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


362-362: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


369-369: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


387-387: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

docs/api.md

17-17: Expected: 2; Actual: 4
Unordered list indentation

(MD007, ul-indent)


18-18: Expected: 2; Actual: 4
Unordered list indentation

(MD007, ul-indent)


36-36: Expected: 2; Actual: 4
Unordered list indentation

(MD007, ul-indent)

scripts/utils/generate_function_hash/README.md

9-9: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


20-20: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


26-26: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


32-32: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🪛 Gitleaks
README.md

371-371: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


374-374: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


374-374: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🪛 LanguageTool
scripts/utils/generate_function_hash/README.md

[uncategorized] ~13-~13: Possible missing comma found.
Context: ...FunctionName with the actual function name and provide the parameter types and nam...

(AI_HYDRA_LEO_MISSING_COMMA)

🔇 Additional comments (52)
scripts/utils/generate_function_hash/main.go (1)

1-9: LGTM!

The package declaration and imports are appropriate for a command-line utility implementing Keccak-256 hashing.

src/go/server/constants.go (2)

1-2: LGTM: Package declaration follows Go conventions.


3-24: Verify the function hash values match their signatures.

The hash values are critical for signature verification. Let's verify they match their corresponding function signatures.

✅ Verification successful

Function hashes are correctly implemented and verified

The verification is complete based on multiple pieces of evidence:

  1. The function hashes in constants.go match the implementation in TransferableAccountStore.sol where each hash is documented with its corresponding function signature in comments.
  2. A dedicated hash generation utility exists with proper implementation using Keccak256 (the correct hashing algorithm for Solidity function signatures).
  3. The README provides examples that match the actual hash values used in the code.
  4. The hashes are consistently used across the codebase and verified in multiple test files.
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify function hashes match their signatures using solidity files

# Search for function signatures in solidity files
echo "Searching for function definitions..."
rg -A 1 "function (ApproveAddress|RevokeApproval|CreateAccount|TransferAccount|DeleteAccount|UnlockAccount|Sign)\b.*TimedSignature" --type solidity

Length of output: 267


Script:

#!/bin/bash
# Let's search for any Solidity or similar contract files first
echo "Searching for contract files..."
fd -e sol -e abi -e json

# Also search for any files containing these function names
echo -e "\nSearching for files with function names..."
rg -l "(ApproveAddress|RevokeApproval|CreateAccount|TransferAccount|DeleteAccount|UnlockAccount|Sign)"

# Look for any documentation or interface definitions
echo -e "\nSearching for interface or documentation files..."
fd -g "*interface*" -g "*contract*" -g "*signature*" -g "*verify*"

Length of output: 1836


Script:

#!/bin/bash
# Let's check the interface and main contract implementation
echo "=== Checking ITransferableAccountStore.sol ==="
cat src/solidity/interfaces/ITransferableAccountStore.sol

echo -e "\n=== Checking TransferableAccountStore.sol ==="
cat src/solidity/TransferableAccountStore.sol

# Also check if there's a hash generation script that might help verify these hashes
echo -e "\n=== Checking hash generation script ==="
cat scripts/utils/generate_function_hash/README.md

Length of output: 19380


Script:

#!/bin/bash
# Let's check the actual hash generation code
echo "=== Checking hash generation implementation ==="
cat scripts/utils/generate_function_hash/main.go

# Also check if there are any test files that verify these hashes
echo -e "\n=== Checking for hash verification tests ==="
rg -l "APPROVE_ADDRESS_FUNCTION_HASH|CREATE_ACCOUNT_FUNCTION_HASH" test/

Length of output: 880

.github/workflows/ci.yaml (1)

5-5: LGTM: Branch trigger configuration looks good.

Adding the 'dev' branch to both push and pull_request triggers is a good practice, ensuring CI coverage for both main and development branches.

Also applies to: 7-7

Makefile (6)

11-11: LGTM! Consistent with devnet-up changes.


17-19: LGTM! Well-structured additional build target.

The target appropriately generates ABI and binary files needed for Go bindings while maintaining consistency with the existing build-solidity target's IR-based compilation.


17-22: LGTM! Well-structured Makefile changes.

The new targets and modifications:

  • Follow consistent naming and formatting patterns
  • Are logically grouped with related targets
  • Support the PR's objectives by adding necessary build and generation capabilities

Also applies to: 44-44, 94-94


7-7: Verify the existence of compose.geth.yaml file.

The Docker Compose file reference has been updated to use a more standardized naming convention.

✅ Verification successful

Docker Compose file reference is valid

The verification confirms that compose.geth.yaml exists in the repository root, validating the updated Docker Compose file reference in the Makefile.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the existence of the new compose file
# Test: Check if the new compose file exists
if [ -f "compose.geth.yaml" ]; then
    echo "compose.geth.yaml exists"
else
    echo "Warning: compose.geth.yaml not found"
fi

Length of output: 89


94-94: Verify the existence of compose.local.yaml file.

The Docker Compose file reference has been updated to use a more standardized naming convention.

✅ Verification successful

File exists and follows consistent naming pattern

The compose.local.yaml file exists in the repository along with other similarly named compose files (compose.geth.yaml, compose.yaml), confirming that the updated reference in the Makefile is correct and follows a consistent naming pattern across the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the existence of the new compose file
# Test: Check if the new compose file exists
if [ -f "compose.local.yaml" ]; then
    echo "compose.local.yaml exists"
else
    echo "Warning: compose.local.yaml not found"
fi

Length of output: 530


Script:

#!/bin/bash
# Let's try a different approach to verify the existence and list any docker compose files
fd -e yaml -e yml compose

Length of output: 77


20-22: Verify the existence and permissions of the binding generation script.

The target references a new script for generating Go bindings.

✅ Verification successful

Script exists and is properly configured for generating Go bindings

The script is executable and correctly set up to generate Go bindings from the Solidity contract using abigen. It specifically handles the TransferableAccountStore contract, which exists in the codebase along with its dependencies.

  • The script expects compiled artifacts in the out/ directory (ABI and bytecode)
  • Generates bindings in src/go/contract/transferable_account_store.go
  • All required Solidity source files are present in the repository
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the existence and permissions of the script
# Test: Check if the script exists and is executable
if [ -x "scripts/utils/gen-solidity-go-bindings.sh" ]; then
    echo "Script exists and is executable"
else
    echo "Warning: Script missing or not executable"
    ls -l scripts/utils/gen-solidity-go-bindings.sh 2>/dev/null || echo "File not found"
fi

Length of output: 530


Script:

#!/bin/bash
# Let's verify the script content to ensure it's properly implemented
cat scripts/utils/gen-solidity-go-bindings.sh

# Also check if there are any related solidity files that would need bindings
fd -e sol

Length of output: 545

test/utils/helpers.go (3)

8-13: LGTM: Import changes align with new functionality

The new imports support the contract-based timed signature implementation.


34-36: Same expiration time issue as CreateAccountHelper

This function has the same hardcoded expiration time. The same refactoring suggestion applies here.


Line range hint 16-69: Verify contract parameter usage across tests

Let's verify that the contract parameter is being passed correctly in all test files using these helpers.

✅ Verification successful

Contract parameter is correctly used across the codebase

The verification shows that:

  • All test files properly initialize taStoreContract via DeployContract or BindToExistingContract
  • The contract is consistently passed to helper functions in all usages
  • The helper functions correctly use the contract parameter to generate timed signatures via NewPbTimedSignature
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for all usages of these helper functions to ensure they're called with the correct contract parameter

echo "Searching for helper function usage patterns..."
rg -A 2 "CreateAccountHelper|ApproveAddressHelper|UnlockAccountHelper" --type go

echo "Searching for potential test setup patterns..."
rg "taStoreContract.*:=.*framework\.NewContract" --type go

Length of output: 4746


Script:

#!/bin/bash
# Let's check how taStoreContract is initialized and passed to these helpers

# First, check for contract initialization in test files
echo "Checking contract initialization in test files..."
rg -B 5 "taStoreContract.*=|taStoreContract.*:=" --type go

# Then check the NewPbTimedSignature implementation to understand contract usage
echo "Checking NewPbTimedSignature implementation..."
rg -A 10 "func NewPbTimedSignature" --type go

Length of output: 5737

scripts/e2e/main.go (3)

17-17: LGTM: Clean import transition from server to contract package.

The import change aligns well with the refactoring objectives.


Line range hint 67-79: LGTM: Clean transition to new signature type.

The function has been properly updated to use the new contract-based signature type with appropriate error handling and field mapping.


Line range hint 73-78: Consider validating timestamp conversion.

The conversion from int64 to uint64 for ValidFor could potentially overflow if validFor is negative. Consider adding validation to ensure the timestamp is positive before the conversion.

src/proto/api/v1/transferable_account.proto (5)

19-22: LGTM! Well-structured enum definition.

The SignatureAlgorithm enum follows protobuf best practices with proper naming and sequencing. The included algorithms (ECDSA and EDDSA) cover the major signature schemes.


94-100: LGTM! Well-structured nonce retrieval messages.

The new messages follow protobuf best practices and provide a clean interface for nonce management.


199-203: LGTM! Well-designed RPC endpoint.

The GetNonce RPC follows RESTful conventions and maintains consistent parameter naming with its message definition.


46-46: Verify the impact of renaming 'to' to 'address'.

The field rename improves clarity but is a breaking change. Ensure all API clients are updated to use the new field name.

#!/bin/bash
# Search for any remaining references to the old field name
rg '"to".*=.*2' --type proto

15-15: Verify the impact of replacing Curve with SignatureAlgorithm.

The change from Curve to SignatureAlgorithm is a breaking change that might affect API clients. While it's a good improvement for clarity and future extensibility, we should ensure all clients are updated accordingly.

✅ Verification successful

Breaking change from Curve to SignatureAlgorithm appears safe to proceed

The verification shows that:

  • The old Curve enum is completely removed from the codebase with no lingering references
  • SignatureAlgorithm is only used in one place (Account message)
  • The change provides better clarity with explicit algorithm types (ECDSA, EDDSA)
  • Field number (5) is preserved, maintaining wire format compatibility

Since this is a clean transition with no conflicting usages, the change appears well-structured. However, as this is a breaking change in the API, ensure this is communicated in release notes and API documentation.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any remaining references to the old Curve enum
rg -i 'curve.*=.*[0-9]' --type proto

Length of output: 139


Script:

#!/bin/bash
# Search for any references to Curve or SignatureAlgorithm in proto files
find . -name "*.proto" -type f -exec grep -l -i "curve\|signaturealgorithm" {} \;

# For each found file, show the content around these terms
for f in $(find . -name "*.proto" -type f); do
  echo "=== $f ==="
  grep -A 5 -B 5 -i "curve\|signaturealgorithm" "$f" || true
done

Length of output: 1315

test/utils/server.go (2)

211-216: LGTM! The GetNonce implementation follows established patterns.

The new function is well-structured and consistent with other endpoint implementations in the file. It:

  • Follows the same URL construction pattern
  • Reuses the existing GetServer helper
  • Maintains consistent error handling
  • Has appropriate return types

211-216: Verify the nonce endpoint integration with signature functionality.

Since this is part of signature-related changes, let's verify the endpoint integration:

✅ Verification successful

Based on the shell script results, I can now generate the final response:

The nonce endpoint integration is properly implemented and verified.

The codebase shows a complete integration chain for nonce functionality:

  • Smart contract has getNonce method defined and implemented (src/go/contract/transferable_account_store.go)
  • Server implementation properly calls the contract method (src/go/server/server.go)
  • API endpoint is defined and mapped correctly (/v1/nonce/{address})
  • Unit tests verify the nonce functionality (src/go/server/server_test.go)
  • The nonce is used correctly in signature generation and verification flows
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the nonce endpoint integration with signature functionality

# Test 1: Check if the nonce endpoint is defined in the API proto files
echo "Checking nonce endpoint definition..."
rg -l "GetNonce" --type proto

# Test 2: Check if there are corresponding signature-related functions that use the nonce
echo "Checking nonce usage in signature functions..."
rg "GetNonce|nonce" --type go -A 5 -B 5

# Test 3: Check for any existing tests that verify nonce behavior
echo "Checking existing nonce-related tests..."
rg "TestGetNonce|test.*Nonce" --type go

Length of output: 101639

docs/api.md (3)

525-525: LGTM!

The GetNonce RPC method is well-integrated into the service definition.


439-439: Verify impact of TransferAccountRequest field rename.

The field rename from to to address is a breaking change. Please ensure:

  1. All clients are updated
  2. Migration guide is provided
  3. Version bump follows semantic versioning
#!/bin/bash
# Search for usages of the old field name in TransferAccountRequest
rg -l 'TransferAccountRequest.*to\s*:' --type proto --type go --type typescript

63-63: Verify impact of Account struct field change.

The replacement of curve with signature_algorithm is a breaking change that might affect existing clients. Please ensure that:

  1. All clients are updated to handle the new field
  2. Migration documentation is provided
  3. Version bump follows semantic versioning
✅ Verification successful

The previous search wasn't successful due to file type issues. Let's try a broader search to understand the Account structure and its usage across the codebase. This will help us verify the impact of changing the field from 'curve' to 'signature_algorithm'.


Based on the code analysis, I can now generate the final response since I have enough context to verify the impact of the field change from 'curve' to 'signature_algorithm'.

Breaking change impact is properly handled

The change from 'curve' to 'signature_algorithm' is a well-structured breaking change that:

  1. Uses a proper enum type (SignatureAlgorithm) with clear values:

    • SignatureAlgorithm_UNSPECIFIED = 0
    • SignatureAlgorithm_ECDSA = 1
    • SignatureAlgorithm_EDDSA = 2
  2. Is reflected consistently across:

    • Proto definitions (Account message)
    • Generated Go bindings
    • API documentation
  3. Provides better semantic meaning by explicitly indicating the signature algorithm rather than just the curve type.

The change appears to be part of a well-designed API evolution that improves clarity while maintaining compatibility through proper enum values.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usages of the old 'curve' field
rg -l 'curve.*Account' --type proto --type go --type typescript

Length of output: 111


Script:

#!/bin/bash
# Search for files containing 'curve' or 'signature_algorithm' in proto definitions
fd -e proto | xargs cat | grep -A 5 -B 5 'message Account'

# Search for Account-related files and their content
fd -i account -e proto -e go -e ts | xargs cat

Length of output: 289641

src/solidity/lib/SignatureVerifier.sol (1)

10-11: Verify all usages of TimedSignature are updated to include new fields

The addition of nonce and targetFunctionHash to the TimedSignature struct may affect other parts of the codebase that use this struct. Ensure that all instances where TimedSignature is instantiated or accessed have been updated accordingly.

Run the following script to find all usages of TimedSignature:

✅ Verification successful

Let me analyze the usage of TimedSignature struct to verify if all instances are properly updated with the new fields. Let me check the struct definition and its usages.


Let me try a different approach to verify the TimedSignature struct usage.


Let me check one more thing to verify the instantiation of TimedSignature in test files since they would show the actual struct construction.


Let me try one final search to find the TimedSignature instantiations in test files.


Based on the gathered information, I can now provide a final response:

All usages of TimedSignature are properly updated with new fields

The verification shows that:

  1. The TimedSignature struct in src/solidity/lib/SignatureVerifier.sol correctly includes both new fields: nonce and targetFunctionHash
  2. All instantiations of the struct (as seen in test/utils/sign.go) include all required fields including the new ones
  3. The contract's verification functions properly handle the complete struct with all fields
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all instances where 'TimedSignature' is used.

# Test: Search for 'TimedSignature' usages.
rg 'TimedSignature'

Length of output: 53806


Script:

#!/bin/bash
# Get the TimedSignature struct definition and its usages in contract code
ast-grep --pattern 'struct TimedSignature {
  $$$
}'

# Get all function calls that create/instantiate TimedSignature
ast-grep --pattern 'TimedSignature({
  $$$
})'

Length of output: 103


Script:

#!/bin/bash
# Get the TimedSignature struct definition
rg -A 10 "struct TimedSignature \{" src/

# Get all instances where TimedSignature is instantiated
rg "return.*TimedSignature\(" src/

Length of output: 1422


Script:

#!/bin/bash
# Get TimedSignature instantiations in test files
rg -A 5 "generateTimedSignature.*return.*TimedSignature" test/

Length of output: 64


Script:

#!/bin/bash
# Search for TimedSignature struct creation in test files
rg -A 6 "return SignatureVerifier\.TimedSignature\s*\{" test/
rg -A 6 "return.*SignatureVerifierTimedSignature\s*\{" test/

Length of output: 543

src/solidity/interfaces/ITransferableAccountStore.sol (7)

54-54: Attention: Changed signature of revokeApproval function

The revokeApproval function signature has changed. Ensure all related code is updated to reflect this change to maintain consistency.

#!/bin/bash
# Description: Find usages of `revokeApproval` function.

# Search for calls to `revokeApproval`
rg '\.revokeApproval\(' --glob '!.*/interfaces/*'

# Search for implementations of `revokeApproval`
rg 'function\s+revokeApproval\(' --glob '!.*/interfaces/*'

42-42: ⚠️ Potential issue

Attention: Changed signature of transferAccount function

The transferAccount function no longer returns bytes memory. This change may affect any code that relies on the returned value. Ensure that all calls and implementations of transferAccount are updated accordingly.

#!/bin/bash
# Description: Find calls to `transferAccount` and check if they expect a return value.

# Search for calls to `transferAccount` expecting a return value
rg '\b.*=\s*.*\.transferAccount\(' --glob '!.*/interfaces/*'

# Search for implementations of `transferAccount`
rg 'function\s+transferAccount\(' --glob '!.*/interfaces/*'

17-20: Update all references from 'Curve' to 'SignatureAlgorithm'

The Curve enum has been replaced with SignatureAlgorithm. Ensure that all references to Curve in the codebase have been updated to SignatureAlgorithm to prevent compilation issues.

#!/bin/bash
# Description: Find all references to 'Curve' enum to update them to 'SignatureAlgorithm'.

# Search for 'Curve' enum references
rg 'Curve\.' --glob '!.*/interfaces/*'

59-64: New functions added: consumeNonce and modified verifyTimedSignature

The new function consumeNonce has been added, and verifyTimedSignature now includes an additional bytes32 parameter and returns a bool. Ensure that:

  • All calls to verifyTimedSignature are updated with the new parameter.
  • Implementations of these functions are correctly updated.
  • Any logic dependent on the previous return type is adjusted.
#!/bin/bash
# Description: Verify usage of `verifyTimedSignature` and `consumeNonce` functions.

# Search for calls to `verifyTimedSignature`
rg '\.verifyTimedSignature\(' --glob '!.*/interfaces/*'

# Search for implementations of `verifyTimedSignature`
rg 'function\s+verifyTimedSignature\(' --glob '!.*/interfaces/*'

# Search for calls to `consumeNonce`
rg '\.consumeNonce\(' --glob '!.*/interfaces/*'

# Search for implementations of `consumeNonce`
rg 'function\s+consumeNonce\(' --glob '!.*/interfaces/*'

43-44: Attention: Changed signature of deleteAccount and unlockAccount functions

The deleteAccount and unlockAccount functions may have altered signatures. Verify that all implementations and call sites are updated to match the new signatures.

#!/bin/bash
# Description: Find usages of `deleteAccount` and `unlockAccount` functions to ensure they match the new signatures.

# Search for calls to `deleteAccount`
rg '\.deleteAccount\(' --glob '!.*/interfaces/*'

# Search for implementations of `deleteAccount`
rg 'function\s+deleteAccount\(' --glob '!.*/interfaces/*'

# Search for calls to `unlockAccount`
rg '\.unlockAccount\(' --glob '!.*/interfaces/*'

# Search for implementations of `unlockAccount`
rg 'function\s+unlockAccount\(' --glob '!.*/interfaces/*'

49-49: Attention: Changed signature of approveAddress function

The approveAddress function signature has been modified. Verify that all calls to this function are updated accordingly to prevent any runtime errors.

#!/bin/bash
# Description: Find usages of `approveAddress` function.

# Search for calls to `approveAddress`
rg '\.approveAddress\(' --glob '!.*/interfaces/*'

# Search for implementations of `approveAddress`
rg 'function\s+approveAddress\(' --glob '!.*/interfaces/*'

13-13: Ensure 'Account' struct changes are propagated throughout the codebase

Adding the signatureAlgorithm field to the Account struct may impact serialization, deserialization, and any modules that interact with Account instances. Verify that all dependent code is updated to handle this new field.

✅ Verification successful

Based on the search results, I can now generate the final response:

The signatureAlgorithm field is properly handled throughout the codebase

The search results show that the Account struct and its new signatureAlgorithm field are consistently handled:

  • The field is included in all Account struct usages in the contract ABI
  • It's properly included in all serialization/deserialization paths (createAccountCallback, getAccount, etc.)
  • The field is stored in the main accountsStore mapping
  • All dependent code (Go bindings, protobuf definitions, tests) has been updated to include the field
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all usages of 'Account' struct to ensure they handle the new 'signatureAlgorithm' field.

# Search for 'Account' struct usages outside the interface
rg 'Account' --glob '!.*/interfaces/*'

Length of output: 2639


Script:

#!/bin/bash
# Let's search for Account struct usage more effectively
# First, find the struct definition and its usages
ast-grep --pattern 'struct Account {
  $$$
}'

# Then search for Account type references
rg 'Account\s+\w+' --type solidity -A 3

# Also search for mapping or array declarations involving Account
rg 'mapping.*Account' --type solidity
rg 'Account\[\]' --type solidity

Length of output: 263


Script:

#!/bin/bash
# Let's try without file type filtering since solidity isn't recognized
# Search for Account struct definition and usages
rg 'struct\s+Account' -A 5

# Search for Account type references
rg 'Account\s+\w+' -A 3

# Search for mappings and arrays
rg 'mapping.*Account'
rg 'Account\[\]'

# Also search for functions that might handle Account data
rg 'function.*Account'

Length of output: 57239

test/integration/auth_test.go (3)

8-12: Imports are correctly added and utilized.

The new import statements are necessary and properly used throughout the code.


80-81: Usage of CREATE_ACCOUNT_FUNCTION_HASH and HexToHash is appropriate.

The functionHash is correctly computed using common.HexToHash(impl.CREATE_ACCOUNT_FUNCTION_HASH), which aligns with the expected format for function hashes.


88-94: Initialization of SignatureVerifierTimedSignature is correct.

All fields are properly assigned, ensuring the signature contains all necessary information for verification.

test/utils/sign.go (1)

93-98: Confirm proper padding lengths in message hash.

Ensure that the padding lengths in LeftPadBytes match the expected byte sizes. Incorrect padding may lead to invalid message hashes.

Review the padding lengths for validFor and nonce:

  • validFor: Padded to 8 bytes.
  • nonce: Padded to 8 bytes.

If the expected sizes differ, adjust accordingly.

scripts/e2e/send_tx/main.go (1)

23-25: Approved New Imports

The added imports framework, impl, and testutil are necessary for the new functionalities and are correctly implemented.

src/solidity/TransferableAccountStore.sol (3)

383-391: Addition of getNonce function is appropriate.

The getNonce function provides external visibility to the current nonce value for a given address, which is useful for clients to generate valid timed signatures.


350-352: 🛠️ Refactor suggestion

Simplify error handling in verifyTimedSignature function.

In the verifyTimedSignature function, the check for timedSignature.targetFunctionHash uses a revert with a custom error. Since this function is intended to return a boolean, consider changing the revert to a simple return false to align with the function's purpose and avoid unexpected exceptions.

Apply this diff to return false instead of reverting:

 if (timedSignature.targetFunctionHash != targetFunctionHash) {
-    revert InvalidTargetFunctionHash();
+    return false;
 }

Likely invalid or redundant comment.


115-118: Ensure consistency of function hash comments and values.

The hardcoded function hash APPROVE_ADDRESS_FUNCTION_HASH at line 115 is accompanied by a comment explaining its origin. Verify that the hash value matches the commented keccak256 of the function signature to prevent mismatches.

Run the following script to confirm the function hash:

Ensure that the output matches 0x16d1dabab53b460506870428d7a255f9bff53294080a73797c114f4e25b5e76f.

✅ Verification successful

Function hash is correctly documented and matches across files

The function hash 0x16d1dabab53b460506870428d7a255f9bff53294080a73797c114f4e25b5e76f is properly documented:

  1. In the Solidity contract, it's preceded by the correct comment showing its source: // keccak256("ApproveAddress(SignatureVerifier.TimedSignature timedSignature,string accountId,address _address)")
  2. The hash value is consistently used in both the Solidity contract and Go server constants
  3. The scripts/utils/generate_function_hash/README.md confirms this is the expected hash value for this function signature

The evidence from multiple files in the codebase confirms the hash value is correct and consistent.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that the function hash matches the commented keccak256 value.

echo -n "ApproveAddress(SignatureVerifier.TimedSignature timedSignature,string accountId,address _address)" | keccak256sum

Length of output: 204


Script:

#!/bin/bash
# Let's first check if there are any comments explaining the hash calculation
rg -B2 -A2 "0x16d1dabab53b460506870428d7a255f9bff53294080a73797c114f4e25b5e76f" --type sol

# Also search for any function signature or hash calculation patterns
ast-grep --pattern 'bytes32 $_ = $$$;'

Length of output: 159


Script:

#!/bin/bash
# Search for the hash value in all files
rg "0x16d1dabab53b460506870428d7a255f9bff53294080a73797c114f4e25b5e76f" -B3 -A3

# Let's also look at the complete file content to understand the context
cat src/solidity/TransferableAccountStore.sol

Length of output: 16895

src/go/server/server.go (1)

Line range hint 493-515: Verify consistent handling of the new return type from populateTimedSignature

The return type of populateTimedSignature has been changed. Ensure all usages handle the new type correctly to prevent runtime errors.

Run the following script to find all usages and verify correct handling:

✅ Verification successful

Let me gather more context about the type handling by checking the implementation in the e2e script since it seems to have a different return type.


Let me check how the return value of populateTimedSignature is used in the server code to ensure proper handling.


Return type change is properly handled across the codebase

The verification shows that:

  1. The server's populateTimedSignature returns a pointer *ct.SignatureVerifierTimedSignature and all its usages in server.go correctly dereference it when passing to contract methods (e.g., *sig).
  2. The e2e test's populateTimedSignature is a different function with different parameters and return type, so there's no conflict.
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all usages of `populateTimedSignature` and check for correct type handling.

rg 'populateTimedSignature\(' -A 2

Length of output: 1927


Script:

#!/bin/bash
# Check the implementation in e2e script and server
cat scripts/e2e/main.go | rg -A 20 'func populateTimedSignature'

Length of output: 950


Script:

#!/bin/bash
# Find usages of the returned signature in server.go
rg -B 2 -A 5 'sig, err := populateTimedSignature\(' src/go/server/server.go

Length of output: 1923

test/e2e/e2e_test.go (4)

Line range hint 355-364: Validate recipient address and signature in transfer

Ensure that the transfer operation uses the correct recipient address and that the signature is generated by the appropriate key holder.

Confirm that tc.sender and tc.to are correctly assigned and that the generated signature aligns with the intended operation.


649-652: Ensure correct address conversion for owner checks

Consistently use crypto.PubkeyToAddress to convert public keys to Ethereum addresses when performing owner checks to avoid mismatches.

The current implementation correctly converts the public key to an address.


93-96: Ensure validFor timestamps are correctly handled

The conversion of tc.validFor to uint64 in NewPbTimedSignature relies on the correctness of the validFor value. Verify that tc.validFor is always a positive integer representing a future timestamp to prevent potential issues with signature validity.

You can run the following script to check for negative or past validFor values in the test cases:


333-336: ⚠️ Potential issue

Use proper address conversion for ApproveAddressRequest

Using tc.to.PublicKey.X.String() may not yield a valid Ethereum address. Instead, convert the public key to an address using crypto.PubkeyToAddress.

Apply this fix:

- Address: tc.to.PublicKey.X.String(),
+ Address: crypto.PubkeyToAddress(tc.to.PublicKey).Hex(),

Likely invalid or redundant comment.

src/go/server/server_test.go (2)

735-736: Ensure correct handling of signature v value during verification

When verifying the signature in tests, remember that Ethereum signatures expect the v value to be in the range of 27 or 28. Adjust accordingly when using the crypto.Ecrecover function.

You can adjust the v value before appending it to the signature for recovery:

recoveryID := signatureBytes[64] - 27
signatureForRecovery := append(signatureBytes[:64], recoveryID)

Ensure consistency between signature generation and verification.


550-556: ⚠️ Potential issue

Handle potential error from UnlockAccount in test setup

In TestSign, the error returned by UnlockAccount is not being checked properly. Ensure that any error is handled to prevent silent failures.

Apply this change:

_, err := s.UnlockAccount(context.Background(), &pb.UnlockAccountRequest{
	// existing code
})
-if err != nil {
-    // Missing error handling
-}
+assert.NoError(t, err, "UnlockAccount call should not return an error")

Likely invalid or redundant comment.

test/TransferableAccountStore.t.sol (3)

33-52: generateTimedSignature function correctly incorporates new parameters

The updated generateTimedSignature function now includes nonce and targetFunctionHash, enhancing security against replay attacks. The implementation aligns with best practices for signature generation.


186-187: Ensure nonce is correctly retrieved for the new owner

After transferring the account ownership to bob, when generating bobSig_0, make sure to retrieve the nonce for bob using tas.getNonce(bob). The current implementation looks correct.


103-103: Ensure equality checks are appropriate for dynamic types

When comparing dynamic types like bytes, using assertEq may not behave as expected. Ensure that the comparison function correctly handles dynamic types.

Run the following script to check if assertEq correctly compares bytes types:

✅ Verification successful

Based on the code analysis, I can now provide the final response:

The assertEq comparison for signatures is appropriate in this context

The signature field in the TimedSignature struct is indeed of type bytes, but in this specific test case, the comparison is valid because:

  1. Both signatures are generated from the same source data using the same private key
  2. The signatures are compared directly after creation, ensuring byte-for-byte equality
  3. The test is specifically checking if the signature was correctly preserved during encoding/decoding
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that assertEq correctly compares bytes variables.

# Test: Search for usage of assertEq with bytes types.
rg 'assertEq\((.*),\s*(.*),\s*".*"\)' -t solidity -A 0 | grep 'bytes'

Length of output: 102


Script:

#!/bin/bash
# Let's first check the actual type of signature in the code
rg -t sol "signature" -B 2 -A 2 test/TransferableAccountStore.t.sol

# Also check the struct definition of TimedSignature
rg -t sol "struct TimedSignature" -B 1 -A 3

Length of output: 169


Script:

#!/bin/bash
# Let's try without file type specification
rg "struct TimedSignature" -A 3 

# Check the content of the test file
cat test/TransferableAccountStore.t.sol

Length of output: 25610

Comment on lines +23 to +27
func keccak256(input string) string {
hash := sha3.NewLegacyKeccak256()
hash.Write([]byte(input))
return hex.EncodeToString(hash.Sum(nil))
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add error handling and documentation.

The function implementation is correct but could be improved with proper error handling and documentation.

Here's a suggested implementation:

+// keccak256 computes the Keccak-256 hash of a function signature.
+// It returns the hex-encoded string of the hash without the '0x' prefix.
+// This is commonly used to generate function selectors for Ethereum smart contracts.
 func keccak256(input string) string {
 	hash := sha3.NewLegacyKeccak256()
-	hash.Write([]byte(input))
+	// Write never returns an error for hash.Hash implementations
+	inputBytes := make([]byte, len(input))
+	copy(inputBytes, input)
+	hash.Write(inputBytes)
 	return hex.EncodeToString(hash.Sum(nil))
 }

Committable suggestion skipped: line range outside the PR's diff.

scripts/utils/generate_function_hash/main.go Outdated Show resolved Hide resolved
test/utils/helpers.go Outdated Show resolved Hide resolved
Comment on lines 16 to 18
func CreateAccountHelper(t *testing.T, taStoreContract *framework.Contract, privKey *ecdsa.PrivateKey) string {
validFor := uint64(time.Now().AddDate(1, 0, 0).Unix())
createSig, err := NewPbTimedSignature(taStoreContract, privKey, validFor, common.HexToHash(impl.CREATE_ACCOUNT_FUNCTION_HASH))
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider making signature expiration time configurable

The one-year expiration time is hardcoded. Consider making this configurable through a parameter or constant to allow for different testing scenarios.

-func CreateAccountHelper(t *testing.T, taStoreContract *framework.Contract, privKey *ecdsa.PrivateKey) string {
-	validFor := uint64(time.Now().AddDate(1, 0, 0).Unix())
+// CreateAccountHelper creates a new account with a timed signature that expires after the specified duration
+func CreateAccountHelper(t *testing.T, taStoreContract *framework.Contract, privKey *ecdsa.PrivateKey, expiresIn time.Duration) string {
+	validFor := uint64(time.Now().Add(expiresIn).Unix())
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func CreateAccountHelper(t *testing.T, taStoreContract *framework.Contract, privKey *ecdsa.PrivateKey) string {
validFor := uint64(time.Now().AddDate(1, 0, 0).Unix())
createSig, err := NewPbTimedSignature(taStoreContract, privKey, validFor, common.HexToHash(impl.CREATE_ACCOUNT_FUNCTION_HASH))
// CreateAccountHelper creates a new account with a timed signature that expires after the specified duration
func CreateAccountHelper(t *testing.T, taStoreContract *framework.Contract, privKey *ecdsa.PrivateKey, expiresIn time.Duration) string {
validFor := uint64(time.Now().Add(expiresIn).Unix())
createSig, err := NewPbTimedSignature(taStoreContract, privKey, validFor, common.HexToHash(impl.CREATE_ACCOUNT_FUNCTION_HASH))

src/proto/api/v1/transferable_account.proto Show resolved Hide resolved
src/go/server/server_test.go Show resolved Hide resolved
test/TransferableAccountStore.t.sol Outdated Show resolved Hide resolved
test/TransferableAccountStore.t.sol Outdated Show resolved Hide resolved
test/TransferableAccountStore.t.sol Outdated Show resolved Hide resolved
test/TransferableAccountStore.t.sol Outdated Show resolved Hide resolved
* update GettingStarted for adding refer commands

* fix indent
Copy link

@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: 1

🧹 Outside diff range and nitpick comments (2)
README.md (2)

64-84: Add language specifiers to code blocks.

Code blocks should specify their language for proper syntax highlighting.

Add language specifiers to the code blocks. For example:

-   ```
+   ```shell
    go run scripts/utils/generate_timed_signature/main.go <private_key> CreateAccount
    ```

Also applies to: 139-158, 212-231, 297-316, 321-335

🧰 Tools
🪛 Markdownlint

64-64: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


71-71: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


76-76: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


374-381: Add warning about gas fees.

When instructing users to send assets from the TA account, it would be helpful to mention that they need to ensure sufficient gas fees are available in the account.

Add a note about gas fees before line 374:

+    Note: Ensure that the TA account has sufficient funds to cover both the transfer amount and gas fees on the target chain.
+
     If you own a TA and hold assets on an external chain with that TA, you can create a Tx to send assets from the TA account and broadcast it to the external chain.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 0c4d79d and bd86eaa.

📒 Files selected for processing (1)
  • README.md (2 hunks)
🧰 Additional context used
🪛 Markdownlint
README.md

383-383: null
Dollar signs used before commands without showing output

(MD014, commands-show-output)


64-64: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


71-71: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


76-76: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


91-91: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


105-105: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


119-119: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


139-139: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


144-144: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


149-149: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


163-163: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


181-181: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


199-199: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


212-212: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


217-217: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


222-222: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


236-236: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


254-254: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


272-272: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


279-279: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


284-284: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


297-297: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


302-302: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


307-307: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


321-321: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


338-338: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


355-355: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


361-361: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


366-366: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


382-382: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


389-389: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


410-410: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🪛 Gitleaks
README.md

286-286: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


286-286: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


391-391: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


396-396: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


397-397: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🔇 Additional comments (3)
README.md (3)

40-42: LGTM: Clear prerequisites section with helpful links.

The prerequisites section clearly outlines the requirements and provides useful links to the faucets.


125-131: LGTM: Clear instructions for SepoliaETH deposit.

The section provides clear instructions for depositing SepoliaETH to the TA's address with appropriate warnings about network selection.


418-419: LGTM: Good reference to API documentation.

The reference to detailed API documentation is helpful for users needing more information.

README.md Outdated Show resolved Hide resolved
Copy link

@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: 0

🧹 Outside diff range and nitpick comments (3)
README.md (3)

61-85: Add language identifiers to code blocks.

Add appropriate language identifiers (e.g., bash, json, shell) to all fenced code blocks for proper syntax highlighting.

Example:

-   ```
+   ```bash
    go run scripts/utils/generate_timed_signature/main.go <your_private_key> CreateAccount
    ```
🧰 Tools
🪛 Markdownlint

65-65: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


72-72: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


77-77: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


124-125: Improve clarity of account creation completion message.

The explanation of accountId and ethereumAddress could be clearer.

-   Once the `txHash` is displayed, the account creation is complete. The displayed `accountId` and `ethereumAddress` are the ID of the account and The account's address on EVM
+   Once the `txHash` is displayed, the account creation is complete. The response includes:
+   - `accountId`: A unique identifier for your Transferable Account
+   - `ethereumAddress`: The EVM-compatible address associated with this account

374-416: Enhance the signing section with important prerequisites.

The signing section should emphasize checking balances and network configuration before proceeding.

Add the following prerequisites:

+    Before proceeding, ensure:
+    1. The TA's ethereum address has sufficient balance on the target chain for the transfer amount and gas fees
+    2. The `WITHDRAW_TESTNET_RPC` in your `.env` file points to a reliable and responsive RPC endpoint
+    3. The target chain's network is stable and processing transactions normally
+
     If you own a TA and hold assets on an external chain...
🧰 Tools
🪛 Markdownlint

383-383: null
Dollar signs used before commands without showing output

(MD014, commands-show-output)


382-382: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


389-389: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


410-410: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🪛 Gitleaks

391-391: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


396-396: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


397-397: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between bd86eaa and a2aee7c.

📒 Files selected for processing (2)
  • Makefile (3 hunks)
  • README.md (3 hunks)
🧰 Additional context used
🪛 Markdownlint
README.md

65-65: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


72-72: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


77-77: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


92-92: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


106-106: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


120-120: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


139-139: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


144-144: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


149-149: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


163-163: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


181-181: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


199-199: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


383-383: null
Dollar signs used before commands without showing output

(MD014, commands-show-output)


212-212: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


217-217: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


222-222: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


236-236: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


254-254: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


272-272: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


279-279: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


284-284: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


297-297: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


302-302: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


307-307: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


321-321: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


338-338: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


355-355: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


361-361: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


366-366: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


382-382: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


389-389: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


410-410: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🪛 Gitleaks
README.md

286-286: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


286-286: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


391-391: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


396-396: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


397-397: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🔇 Additional comments (8)
Makefile (4)

47-47: LGTM! Note about test caching.

Adding -count=1 ensures tests always run fresh without using cached results. While this is good for reliability, be aware it might slightly increase CI execution time.


99-99: Verify the e2e test compose file rename.

The Docker Compose file for e2e tests has been renamed to follow the new naming convention.

#!/bin/bash
# Description: Verify the existence of the new e2e test compose file

# Test 1: Check if the new compose file exists
if [ ! -f "compose.local.yaml" ]; then
    echo "Warning: compose.local.yaml not found"
fi

# Test 2: Search for any remaining references to the old filename
rg "local\.compose\.yaml"

17-22: Verify the Go bindings generation script and add documentation.

The new targets enhance the build system by generating necessary Solidity artifacts and Go bindings. However, we should ensure the script exists and add documentation about the purpose of these targets.

#!/bin/bash
# Description: Verify the existence and permissions of the Go bindings generation script

# Test 1: Check if the script exists and is executable
if [ ! -x "scripts/utils/gen-solidity-go-bindings.sh" ]; then
    echo "Warning: gen-solidity-go-bindings.sh not found or not executable"
fi

# Test 2: Examine the script content
if [ -f "scripts/utils/gen-solidity-go-bindings.sh" ]; then
    cat "scripts/utils/gen-solidity-go-bindings.sh"
fi

Consider adding comments to document these targets:

+# Build Solidity contracts with ABI and binary output files
 build-solidity-extra:
 	forge build --extra-output-files abi bin --via-ir

+# Generate Go bindings from Solidity contract artifacts
 gen-solidity-go-bindings:
 	./scripts/utils/gen-solidity-go-bindings.sh

7-7: Verify the Docker Compose file rename.

The Docker Compose file has been renamed from suave-geth.compose.yaml to compose.geth.yaml. While the new name follows a more consistent naming pattern, we should ensure this change is coordinated across the codebase.

Also applies to: 11-11

✅ Verification successful

Let me try another verification approach since the previous script had some issues.


Docker Compose file rename is properly coordinated

The verification shows that:

  • The new file compose.geth.yaml exists in the repository
  • No references to the old filename suave-geth.compose.yaml remain in the codebase
  • The rename was done intentionally in commit 5b19cd1 with message "chore: rename suave-geth.compose.yaml to compose.geth.yaml"
  • Only the Makefile references the new filename, which is correct as it's the change we're reviewing
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the existence of the new compose file and check for any remaining references to the old filename

# Test 1: Check if the new compose file exists
if [ ! -f "compose.geth.yaml" ]; then
    echo "Warning: compose.geth.yaml not found"
fi

# Test 2: Search for any remaining references to the old filename
rg "suave-geth\.compose\.yaml"

Length of output: 516


Script:

#!/bin/bash
# Check for both old and new compose file names
echo "Checking for compose files:"
ls compose.geth.yaml suave-geth.compose.yaml 2>/dev/null || true

echo -e "\nSearching for references to both filenames:"
echo "Old filename (suave-geth.compose.yaml):"
rg -l "suave-geth\.compose\.yaml" || true
echo -e "\nNew filename (compose.geth.yaml):"
rg -l "compose\.geth\.yaml" || true

# Check git history for the rename
echo -e "\nChecking git history for file rename:"
git log --all --full-history -- "*suave-geth.compose.yaml" "*compose.geth.yaml" || true

Length of output: 4923

README.md (4)

41-43: LGTM: Clear prerequisites and setup instructions.

The addition of Sepolia Testnet requirements and faucet links improves the documentation's completeness.


73-85: Remove sensitive information from example outputs.

The example outputs contain private keys and API endpoints that should be replaced with placeholders.

Also applies to: 390-393

🧰 Tools
🪛 Markdownlint

77-77: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


289-369: LGTM: Well-documented unlock functionality.

The new unlock functionality section is well-structured with clear examples and verification steps.

🧰 Tools
🪛 Markdownlint

297-297: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


302-302: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


307-307: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


321-321: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


338-338: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


355-355: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


361-361: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


366-366: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


418-419: LGTM: Good reference to detailed API documentation.

The link to API documentation provides a good reference for advanced usage.

Copy link

@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: 1

🧹 Outside diff range and nitpick comments (3)
src/go/server/server.go (3)

71-106: Enhance error messages with more context

The error messages in the constructor could be more specific to help with debugging. Consider including relevant parameters in the error messages.

Apply this diff to improve error messages:

-		return nil, fmt.Errorf("failed to bind to existing contract: %v", err)
+		return nil, fmt.Errorf("failed to bind to contract at address %s: %v", taStoreContractAddr, err)

-		return nil, fmt.Errorf("failed to dial RPC: %v", err)
+		return nil, fmt.Errorf("failed to dial RPC at %s: %v", rpcUrl, err)

-		return nil, fmt.Errorf("failed to bind to contract: %v", err)
+		return nil, fmt.Errorf("failed to create contract binding at address %s: %v", taStoreContractAddr, err)

392-405: Add input validation for address parameter

The GetNonce method should validate that the input address is a valid Ethereum address before proceeding.

Apply this diff to add validation:

 func (s *server) GetNonce(ctx context.Context, req *pb.GetNonceRequest) (*pb.GetNonceResponse, error) {
+	if !common.IsHexAddress(req.Address) {
+		return nil, fmt.Errorf("invalid ethereum address format: %s", req.Address)
+	}
 	result := s.taStoreContract.Call("getNonce", []interface{}{common.HexToAddress(req.Address)})

Line range hint 481-503: Add validation for TimedSignature fields

The populateTimedSignature function should validate all required fields before processing.

Apply this diff to add comprehensive validation:

 func populateTimedSignature(sig *pb.TimedSignature) (*ct.SignatureVerifierTimedSignature, error) {
+	if sig == nil {
+		return nil, fmt.Errorf("timed signature is nil")
+	}
+	if sig.ValidFor <= 0 {
+		return nil, fmt.Errorf("invalid ValidFor value: must be positive")
+	}
+	if sig.Signer == "" {
+		return nil, fmt.Errorf("signer address is required")
+	}
+	if !common.IsHexAddress(sig.Signer) {
+		return nil, fmt.Errorf("invalid signer address format: %s", sig.Signer)
+	}
+	if sig.TargetFunctionHash == "" {
+		return nil, fmt.Errorf("target function hash is required")
+	}
 	messageHash, err := hex.DecodeString(sig.MessageHash)
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between a2aee7c and 5444164.

📒 Files selected for processing (2)
  • .coderabbit.yaml (1 hunks)
  • src/go/server/server.go (10 hunks)
✅ Files skipped from review due to trivial changes (1)
  • .coderabbit.yaml
🧰 Additional context used
📓 Learnings (1)
src/go/server/server.go (1)
Learnt from: peaceandwhisky
PR: mycel-labs/astraeus#56
File: src/go/server/server.go:156-163
Timestamp: 2024-10-19T17:24:44.357Z
Learning: In `src/go/server/server.go`, within the `CreateAccount` method, `caEvent["account"]` is a mapping holding a value of type `interface{}`. Therefore, it cannot be directly cast to a struct like `Account` without a more complex approach.

Comment on lines +225 to +227
receipt, err := s.waitForTransaction(ctx, tx)
if err != nil {
return nil, err
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add timeout handling for transaction mining

The waitForTransaction calls could potentially block indefinitely. Consider adding a timeout context to ensure the operations don't hang indefinitely.

Apply this pattern to all transaction wait calls:

+	ctx, cancel := context.WithTimeout(ctx, 5*time.Minute)
+	defer cancel()
	receipt, err := s.waitForTransaction(ctx, tx)

Also update the waitForTransaction helper to handle context cancellation:

 func (s *server) waitForTransaction(ctx context.Context, tx *types.Transaction) (*types.Receipt, error) {
+	if ctx.Err() != nil {
+		return nil, ctx.Err()
+	}
 	receipt, err := bind.WaitMined(ctx, s.client, tx)
 	if err != nil {
-		log.Printf("error waiting for transaction to be mined: %v", err)
+		if ctx.Err() != nil {
+			return nil, fmt.Errorf("transaction wait cancelled: %v", ctx.Err())
+		}
+		log.Printf("error waiting for transaction to be mined: %v", err)
 		return nil, err
 	}

Also applies to: 245-247, 266-268, 286-288, 306-308

* update TransferableAccountStore.t.sol

* remove godotenv from server.go

* update CreateAccountHelper

* update UnlockAccountHelper

* update ApproveAddressHelper

* update literalCase for functionHash

* Update validFor type to uint64

* update generate_function_hash script

* update generate_timed_signature script

* update SignatureVerifier.sol

* update sign.go for adding error handling

* Remove redundant error handling

* Revert "update SignatureVerifier.sol"

This reverts commit 29029bb.

* Add files generated during build execution
Copy link

@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: 5

🧹 Outside diff range and nitpick comments (18)
docs/how-to-test.md (2)

1-14: Add prerequisites section

Consider adding a prerequisites section before the steps to clarify required tools and dependencies (e.g., make, required Go version, Solidity compiler version).


24-32: Enhance test execution documentation

The test commands would benefit from additional context about what they test and expected outcomes.

Add descriptions for each test command, for example:

### Execute tests

#### Go Tests
```jsx
make test-go

Runs unit tests for the Go implementation, including [describe what's being tested]

Solidity Tests

make test-solidity

Executes smart contract tests, verifying [describe what's being tested]

Expected output examples would also be helpful.


</blockquote></details>
<details>
<summary>scripts/utils/generate_function_hash/main.go (1)</summary><blockquote>

`11-26`: **Enhance input validation and CLI interface.**

While the basic argument handling is good, consider these improvements:
1. Add validation for the function signature format
2. Implement standard CLI flags (-h/--help)

Here's a suggested implementation:

```diff
+import (
+	"flag"
+	"regexp"
+)
+
+var functionSigPattern = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_]*\((([a-zA-Z][a-zA-Z0-9]*)(,[a-zA-Z][a-zA-Z0-9]*)*)*\)$`)
+
 func main() {
+	help := flag.Bool("h", false, "Display help")
+	flag.Parse()
+
+	if *help {
+		fmt.Fprintln(os.Stderr, "Usage: go run main.go <function_signature>")
+		fmt.Fprintln(os.Stderr, "Example: go run main.go \"transfer(address,uint256)\"")
+		fmt.Fprintln(os.Stderr, "\nFunction signature format: name(type1,type2,...)")
+		os.Exit(0)
+	}
+
-	if len(os.Args) < 2 {
+	args := flag.Args()
+	if len(args) < 1 {
 		fmt.Fprintln(os.Stderr, "Usage: go run main.go <function_signature>")
 		fmt.Fprintln(os.Stderr, "Example: go run main.go \"transfer(address,uint256)\"")
 		os.Exit(1)
 	}
 
-	argument := os.Args[1]
+	argument := args[0]
 	if len(argument) == 0 {
 		fmt.Fprintln(os.Stderr, "Error: Empty input string")
 		os.Exit(1)
 	}
 
+	if !functionSigPattern.MatchString(argument) {
+		fmt.Fprintln(os.Stderr, "Error: Invalid function signature format")
+		fmt.Fprintln(os.Stderr, "Expected format: name(type1,type2,...)")
+		os.Exit(1)
+	}
+
 	hash := keccak256(argument)
 	fmt.Printf("0x%s\n", hash)
 }
scripts/utils/generate_timed_signature/main.go (3)

34-50: Consider improving target function handling

The current implementation could be enhanced for better maintainability and reliability:

  1. Define constants for the target function names to avoid magic strings
  2. Add validation for function hash values
+const (
+	CreateAccountFunc   = "CreateAccount"
+	ApproveAddressFunc = "ApproveAddress"
+	// ... other function names
+)

 switch targetFunction {
-	case "CreateAccount":
+	case CreateAccountFunc:
 		targetFunctionHash = common.HexToHash(impl.CREATE_ACCOUNT_FUNCTION_HASH)
-	case "ApproveAddress":
+	case ApproveAddressFunc:
 		targetFunctionHash = common.HexToHash(impl.APPROVE_ADDRESS_FUNCTION_HASH)
 		// ... other cases
 }

Also, consider adding a verification step:

// Verify function hash is not empty
if targetFunctionHash == [32]byte{} {
    log.Fatalf("Invalid function hash for target function: %s", targetFunction)
}

53-61: Enhance private key error messages

The error messages could be more informative about the expected format and requirements.

 privateKeyBytes, err := hex.DecodeString(os.Args[1])
 if err != nil {
-	log.Fatalf("failed to decode hex string: %v", err)
+	log.Fatalf("Invalid private key format. Expected a hex string (64 characters): %v", err)
 }
 privKey, err := crypto.ToECDSA(privateKeyBytes)
 if err != nil {
-	log.Fatalf("Failed to create private key: %v", err)
+	log.Fatalf("Failed to create ECDSA private key. Ensure the key is a valid secp256k1 private key: %v", err)
 }

71-71: Make signature validity period configurable

The 24-hour validity period is hard-coded. Consider making it configurable through environment variables or command-line flags.

-validFor := uint64(time.Now().Unix() + 86400)
+validityDuration := 24 * time.Hour
+if envDuration := os.Getenv("SIGNATURE_VALIDITY_DURATION"); envDuration != "" {
+	parsed, err := time.ParseDuration(envDuration)
+	if err != nil {
+		log.Fatalf("Invalid SIGNATURE_VALIDITY_DURATION format. Expected a duration string (e.g., '24h'): %v", err)
+	}
+	validityDuration = parsed
+}
+validFor := uint64(time.Now().Add(validityDuration).Unix())
test/utils/sign.go (3)

19-47: Consider parameterizing the validity period.

The validity period is currently hardcoded to 1 year. Consider making it configurable to support different use cases and testing scenarios.

-func NewAccount(taStoreContract *framework.Contract, privateKey *ecdsa.PrivateKey) (*pb.Account, error) {
+func NewAccount(taStoreContract *framework.Contract, privateKey *ecdsa.PrivateKey, validityDuration time.Duration) (*pb.Account, error) {
 	targetFunctionHash := common.HexToHash(impl.CREATE_ACCOUNT_FUNCTION_HASH)
-	validFor := uint64(time.Now().AddDate(1, 0, 0).Unix())
+	validFor := uint64(time.Now().Add(validityDuration).Unix())

64-85: Add documentation to explain the public/private function pattern.

Consider adding documentation to explain why there are two functions and when to use each one. This will help maintainers understand the separation of concerns.

Add comments like:

// NewTimedSignature provides a public interface for generating timed signatures.
// It delegates to newTimedSignature for the actual implementation.
func NewTimedSignature(...) {...}

// newTimedSignature handles the core signature generation logic.
// It is kept private to ensure all signature generation goes through the proper public interfaces.
func newTimedSignature(...) {...}

99-108: Enhance cryptographic operation documentation.

While the code has basic comments explaining the steps, consider adding more detailed documentation about:

  • The purpose of each component in the message hash
  • The significance of the padding lengths
  • The rationale behind the Mycel-specific prefix
  • The reason for adjusting the v value by 27

Add more detailed comments like:

// generateTimedSignature creates a timed signature that includes:
// - validFor: 8-byte timestamp for signature expiration
// - address: 20-byte signer's address
// - nonce: 8-byte replay protection value
// - targetFunctionHash: 32-byte function selector
//
// The signature follows the Mycel protocol:
// 1. Components are concatenated and hashed with Keccak256
// 2. Result is prefixed with "\x19Mycel Signed Message:\n32" and hashed again
// 3. Final hash is signed with ECDSA
// 4. V value is adjusted by +27 for EVM compatibility
src/solidity/TransferableAccountStore.sol (1)

384-391: Consider adding events for nonce updates.

For better transparency and off-chain tracking, consider emitting an event when a nonce is updated in the consumeNonce function.

+    event NonceUpdated(address indexed signer, uint64 newNonce);

     function consumeNonce(SignatureVerifier.TimedSignature calldata timedSignature, bytes32 targetFunctionHash)
         public
         returns (bool)
     {
         require(timedSignature.nonce == nonces[timedSignature.signer], "Invalid nonce");
         bool isValid = verifyTimedSignature(timedSignature, targetFunctionHash);
         if (isValid) {
             nonces[timedSignature.signer]++;
+            emit NonceUpdated(timedSignature.signer, nonces[timedSignature.signer]);
         }
         return isValid;
     }
docs/openapi.yaml (2)

320-343: Add descriptive documentation for the nonce endpoint

While the endpoint is well-structured, it would benefit from additional documentation to help API consumers understand:

  • The purpose and lifecycle of the nonce
  • Expected format of the address parameter (e.g., Ethereum address format)
  • Common use cases and integration patterns

Add descriptions like this:

 /v1/nonce/{address}:
     get:
+        description: Retrieves the current nonce for the given address. The nonce is used to prevent replay attacks in timed signatures.
         tags:
             - AccountService
         operationId: AccountService_GetNonce
         parameters:
             - name: address
               in: path
               required: true
+              description: Ethereum address in hex format (0x...)
               schema:
                 type: string

357-357: Schema changes look good with minor suggestions

The schema updates improve security and consistency:

  • Addition of nonce-based signature verification
  • Standardized naming conventions
  • More complete account information

Consider these minor improvements:

Add descriptions for the new fields:

 signatureAlgorithm:
     type: integer
     format: enum
+    description: Algorithm used for generating and verifying signatures

 nonce:
     type: string
+    description: Unique number used once to prevent replay attacks

 targetFunctionHash:
     type: string
+    description: Hash of the target function to be called, ensuring signature can't be reused for other functions

 ethereumAddress:
     type: string
+    description: The Ethereum address associated with this account

Also applies to: 493-496, 503-503, 394-395

test/e2e/e2e_test.go (2)

148-151: Consider using test setup helpers to reduce boilerplate

The account creation and error handling code is repeated across multiple test cases. Consider creating a test helper function that encapsulates this common setup pattern.

func setupTestAccount(t *testing.T, creator *ecdsa.PrivateKey) string {
    accountId, err := testutil.CreateAccountHelper(t, taStoreContract, creator)
    if err != nil {
        t.Fatalf("Failed to create account: %v", err)
    }
    return accountId
}

Also applies to: 211-214, 280-283, 345-348, 431-434, 569-572, 628-631, 689-692, 700-703, 741-744, 752-755


286-291: Consider using test helper functions for signature generation

The signature generation code is repeated across multiple test functions. Consider creating a helper function to reduce duplication and improve maintainability.

func generateTimedSignature(t *testing.T, contract *framework.Contract, signer *ecdsa.PrivateKey, validFor int64, functionHash string) *pb.TimedSignature {
    sig, err := testutil.NewPbTimedSignature(contract, signer, uint64(validFor), common.HexToHash(functionHash))
    if err != nil {
        t.Fatalf("Failed to generate timed signature: %v", err)
    }
    return sig
}

Also applies to: 443-448, 531-536

test/TransferableAccountStore.t.sol (2)

13-36: LGTM! Consider grouping related constants.

The constants and error definitions are well-structured. Consider grouping the function hash constants into a separate library for better maintainability if they are used across multiple test files.


79-81: Consider a more robust approach to signature invalidation.

Directly manipulating signature bytes using XOR might not be the most reliable way to test invalid signatures. Consider generating a completely different signature or using a different private key.

-sig0.signature[0] ^= 0xFF;
+// Option 1: Use a different private key
+SignatureVerifier.TimedSignature memory invalidSig = generateTimedSignature(
+    sig0.validFor,
+    sig0.signer,
+    BOB_PRIVATE_KEY, // Using a different private key
+    sig0.nonce,
+    sig0.targetFunctionHash
+);
+
+// Option 2: Use an invalid message hash
+sig0.messageHash = keccak256("invalid");
docs/index.html (2)

771-776: Add descriptions for new fields

The new fields (ethereum_address, nonce, target_function_hash) lack descriptions in the documentation. Consider adding descriptions to clarify their purpose and usage.

Add descriptions like:

-  <td><p> </p></td>
+  <td><p>Ethereum address associated with the account</p></td>

-  <td><p> </p></td>
+  <td><p>Nonce value for replay protection</p></td>

-  <td><p>hex encoded </p></td>
+  <td><p>hex encoded hash of the target function for function-specific signatures</p></td>

Also applies to: 1266-1278


Line range hint 1392-1413: Add descriptions for SignatureAlgorithm enum values

The SignatureAlgorithm enum values lack descriptions. Consider adding descriptions to clarify their purpose.

Add descriptions like:

-  <td><p></p></td>
+  <td><p>Default value, should not be used</p></td>

-  <td><p></p></td>
+  <td><p>ECDSA (Elliptic Curve Digital Signature Algorithm)</p></td>

-  <td><p></p></td>
+  <td><p>EdDSA (Edwards-curve Digital Signature Algorithm)</p></td>
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 5444164 and 686fff6.

📒 Files selected for processing (10)
  • docs/how-to-test.md (1 hunks)
  • docs/index.html (11 hunks)
  • docs/openapi.yaml (5 hunks)
  • scripts/utils/generate_function_hash/main.go (1 hunks)
  • scripts/utils/generate_timed_signature/main.go (1 hunks)
  • src/solidity/TransferableAccountStore.sol (10 hunks)
  • test/TransferableAccountStore.t.sol (6 hunks)
  • test/e2e/e2e_test.go (18 hunks)
  • test/utils/helpers.go (3 hunks)
  • test/utils/sign.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/utils/helpers.go
🧰 Additional context used
🪛 Gitleaks (8.21.2)
docs/how-to-test.md

19-19: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🔇 Additional comments (17)
scripts/utils/generate_function_hash/main.go (3)

1-9: LGTM! Clean and well-organized imports.

The imports are properly organized and include all necessary packages for the functionality.


28-32: 🛠️ Refactor suggestion

Add proper documentation and improve implementation.

The function needs documentation and better memory handling.

Apply this improvement:

+// keccak256 computes the Keccak-256 hash of a function signature.
+// It returns the hex-encoded string of the hash without the '0x' prefix.
+// This is commonly used to generate function selectors for Ethereum smart contracts.
 func keccak256(input string) string {
 	hash := sha3.NewLegacyKeccak256()
-	hash.Write([]byte(input))
+	// Write never returns an error for hash.Hash implementations
+	inputBytes := make([]byte, len(input))
+	copy(inputBytes, input)
+	hash.Write(inputBytes)
 	return hex.EncodeToString(hash.Sum(nil))
 }

1-32: Verify uniqueness of the utility.

Let's ensure this utility isn't duplicating functionality already present in the codebase.

✅ Verification successful

The initial results show other files using Keccak256 and similar CLI utilities. Let's examine their implementations to determine if there's actual duplication of functionality or if they serve different purposes.


Utility serves a unique purpose

The verification confirms this is a unique utility. While other files in the codebase use Keccak256 and CLI arguments, they serve different purposes:

  • generate_timed_signature/main.go uses predefined function hashes for specific contract functions
  • The new utility (generate_function_hash/main.go) is a general-purpose tool for generating function hashes from any function signature
  • Other files found are either protobuf generated code or transaction-related utilities
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for similar Keccak/function hash utilities
rg -l "NewLegacyKeccak256|function.*hash|keccak256" --type go

# Search for similar CLI utilities
fd -e go -x grep -l "os.Args" {} \;

Length of output: 453


Script:

#!/bin/bash
# Let's examine the content of files that use Keccak/function hash
ast-grep --pattern 'func $_ ($$$) {
  $$$
  NewLegacyKeccak256()
  $$$
}'

# Also check the specific implementation in generate_timed_signature
cat scripts/utils/generate_timed_signature/main.go

Length of output: 2867

scripts/utils/generate_timed_signature/main.go (2)

26-28: ⚠️ Potential issue

Consider more secure methods for private key handling

Passing private keys through command-line arguments poses security risks as they may be visible in process listings and shell history.

Consider reading the private key from an environment variable or a secure file instead:

-	if len(os.Args) != 3 {
-		log.Fatalf("Usage: %s <privateKey> <targetFunction>", os.Args[0])
-	}
+	if len(os.Args) != 2 {
+		log.Fatalf("Usage: %s <targetFunction>", os.Args[0])
+	}
+	privateKeyHex := os.Getenv("PRIVATE_KEY_HEX")
+	if privateKeyHex == "" {
+		log.Fatalf("PRIVATE_KEY_HEX environment variable is not set")
+	}

79-86: 🛠️ Refactor suggestion

Use proper JSON encoding instead of manual string formatting

Manual JSON string construction is error-prone and may not properly escape special characters.

+import "encoding/json"

+type Proof struct {
+	ValidFor           uint64 `json:"validFor"`
+	MessageHash        string `json:"messageHash"`
+	Signature         string `json:"signature"`
+	Signer            string `json:"signer"`
+	Nonce             uint64 `json:"nonce"`
+	TargetFunctionHash string `json:"targetFunctionHash"`
+}

-fmt.Printf("\"proof\": {\n")
-fmt.Printf("  \"validFor\": %d,\n", validFor)
-fmt.Printf("  \"messageHash\": \"%s\",\n", timedSignature.MessageHash)
-fmt.Printf("  \"signature\": \"%s\",\n", timedSignature.Signature)
-fmt.Printf("  \"signer\": \"%s\",\n", timedSignature.Signer)
-fmt.Printf("  \"nonce\": %d,\n", timedSignature.Nonce)
-fmt.Printf("  \"target_function_hash\": \"%s\"\n", timedSignature.TargetFunctionHash)
-fmt.Printf("}\n")
+proof := Proof{
+	ValidFor:           validFor,
+	MessageHash:        timedSignature.MessageHash,
+	Signature:         timedSignature.Signature,
+	Signer:            timedSignature.Signer,
+	Nonce:             timedSignature.Nonce,
+	TargetFunctionHash: timedSignature.TargetFunctionHash,
+}
+
+output := map[string]Proof{"proof": proof}
+jsonBytes, err := json.MarshalIndent(output, "", "  ")
+if err != nil {
+	log.Fatalf("Failed to marshal proof to JSON: %v", err)
+}
+fmt.Println(string(jsonBytes))
test/utils/sign.go (2)

49-62: LGTM! Clean and well-structured protobuf conversion.

The function properly handles the conversion from internal signature type to protobuf type with appropriate error handling and safe encoding of binary data.


92-95: ⚠️ Potential issue

Correct the type assertion for nonce value.

The type assertion result[0].(uint64) may fail because Solidity uint256 values are returned as *big.Int in Go Ethereum. This can lead to a runtime error.

-	nonce, ok := result[0].(uint64)
+	nonceBigInt, ok := result[0].(*big.Int)
 	if !ok {
 		return 0, fmt.Errorf("nonce data type is unexpected")
 	}
-	return nonce, nil
+	return nonceBigInt.Uint64(), nil
src/solidity/TransferableAccountStore.sol (5)

26-26: LGTM! Gas-efficient state variable declarations.

The changes improve gas efficiency and security:

  • Making KEY_FA constant saves gas as it's stored in bytecode
  • Using uint64 for nonces provides a good balance between range and gas cost

Also applies to: 30-30


43-50: Standardize error naming for consistency.

The error naming follows a good pattern except for OnlyUnlockAccount. Consider renaming it to AccountLocked for consistency with other error names.


193-197: Prevent replay attacks in createAccount function.

The function uses verifyTimedSignature without consuming the nonce, which could allow replay attacks.


299-309: Prevent replay attacks in sign function.

The function uses verifyTimedSignature without consuming the nonce, which could allow replay attacks.


332-332: Use custom error for nonce validation to save gas.

Replace the require statement with a custom error to reduce gas costs.

test/e2e/e2e_test.go (1)

52-55: Avoid hardcoding private keys in test code

Even in test environments, it's recommended to load sensitive information from environment variables or configuration files.

test/TransferableAccountStore.t.sol (2)

Line range hint 37-63: LGTM! Robust signature generation implementation.

The updated generateTimedSignature function properly incorporates nonce and targetFunctionHash, enhancing the security of the signature verification process.


Line range hint 505-524: LGTM! Well-implemented string utilities.

The StringUtils library provides a clean and efficient implementation for bytes16 to string conversion.

docs/index.html (2)

259-265: Well-structured GetNonce API addition

The new GetNonce API endpoint is well-designed, following REST conventions with appropriate HTTP method (GET) and path parameter usage.

Also applies to: 881-927, 1489-1494, 1617-1623


617-618: Improved field naming from curve to signature_algorithm

The rename provides better clarity about the field's purpose and maintains consistency with the enum type.

Comment on lines +17 to +22
```jsx
#Local Testnet
PRIVATE_KEY=91ab9a7e53c220e6210460b65a7a3bb2ca181412a8a7b43ff336b3df1737ce12
TA_STORE_CONTRACT_ADDRESS=0xd594760B2A36467ec7F0267382564772D7b0b73c
RPC_URL=http://localhost:8545
```
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Security: Replace example private key with a clearly marked placeholder

The current example private key could be mistaken for a real key, which poses a security risk. Additionally, it's not clearly marked as an example value.

Apply this diff to make the examples more secure and explicit:

 #Local Testnet
-PRIVATE_KEY=91ab9a7e53c220e6210460b65a7a3bb2ca181412a8a7b43ff336b3df1737ce12
+PRIVATE_KEY=<YOUR-PRIVATE-KEY-HERE> # Example: 0xabc...123
-TA_STORE_CONTRACT_ADDRESS=0xd594760B2A36467ec7F0267382564772D7b0b73c
+TA_STORE_CONTRACT_ADDRESS=<CONTRACT-ADDRESS> # Example: 0xd594...b73c
 RPC_URL=http://localhost:8545

Also, consider adding a warning note:

> ⚠️ WARNING: Never commit real private keys to documentation or source control. The values above are examples only.
🧰 Tools
🪛 Gitleaks (8.21.2)

19-19: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

```jsx
#Local Testnet
PRIVATE_KEY=91ab9a7e53c220e6210460b65a7a3bb2ca181412a8a7b43ff336b3df1737ce12
TA_STORE_CONTRACT_ADDRESS=0xd594760B2A36467ec7F0267382564772D7b0b73c
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

Update example contract address to match the one in README

The contract address in the documentation (0xd594760B2A36467ec7F0267382564772D7b0b73c) differs from the one used in the README (0xEa8a6ce7098B79Bd8B4920120734a5081046C44F). For consistency in documentation, we should use the same example address across all documentation files.

🔗 Analysis chain

Verify the example contract address

Let's verify if this contract address is used elsewhere in the codebase to ensure consistency.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other occurrences of this contract address
rg -i "0xd594760B2A36467ec7F0267382564772D7b0b73c"

# Check if there are other contract addresses that might be more appropriate as examples
rg -i "TA_STORE_CONTRACT_ADDRESS"

Length of output: 2210

Comment on lines +63 to +68
fr := framework.New(framework.WithCustomConfig(os.Getenv("PRIVATE_KEY"), os.Getenv("RPC_URL")))

privateKeyHex := os.Args[2]
privateKey, err := crypto.HexToECDSA(privateKeyHex)
log.Printf("Using TA_STORE_CONTRACT_ADDRESS: %s", os.Getenv("TA_STORE_CONTRACT_ADDRESS"))
taStoreContract, err := fr.Suave.BindToExistingContract(common.HexToAddress(os.Getenv("TA_STORE_CONTRACT_ADDRESS")), testutil.TAStoreContractPath)
if err != nil {
log.Fatalf("Invalid private key: %v", err)
log.Fatalf("Failed to bind to existing contract: %v", err)
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add validation for required environment variables

The code should validate all required environment variables before using them.

+func getRequiredEnv(key string) string {
+	value := os.Getenv(key)
+	if value == "" {
+		log.Fatalf("Required environment variable %s is not set", key)
+	}
+	return value
+}

-fr := framework.New(framework.WithCustomConfig(os.Getenv("PRIVATE_KEY"), os.Getenv("RPC_URL")))
+privateKey := getRequiredEnv("PRIVATE_KEY")
+rpcURL := getRequiredEnv("RPC_URL")
+taStoreAddress := getRequiredEnv("TA_STORE_CONTRACT_ADDRESS")
+
+fr := framework.New(framework.WithCustomConfig(privateKey, rpcURL))

-log.Printf("Using TA_STORE_CONTRACT_ADDRESS: %s", os.Getenv("TA_STORE_CONTRACT_ADDRESS"))
+log.Printf("Using TA_STORE_CONTRACT_ADDRESS: %s", taStoreAddress)
-taStoreContract, err := fr.Suave.BindToExistingContract(common.HexToAddress(os.Getenv("TA_STORE_CONTRACT_ADDRESS")), testutil.TAStoreContractPath)
+taStoreContract, err := fr.Suave.BindToExistingContract(common.HexToAddress(taStoreAddress), testutil.TAStoreContractPath)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fr := framework.New(framework.WithCustomConfig(os.Getenv("PRIVATE_KEY"), os.Getenv("RPC_URL")))
privateKeyHex := os.Args[2]
privateKey, err := crypto.HexToECDSA(privateKeyHex)
log.Printf("Using TA_STORE_CONTRACT_ADDRESS: %s", os.Getenv("TA_STORE_CONTRACT_ADDRESS"))
taStoreContract, err := fr.Suave.BindToExistingContract(common.HexToAddress(os.Getenv("TA_STORE_CONTRACT_ADDRESS")), testutil.TAStoreContractPath)
if err != nil {
log.Fatalf("Invalid private key: %v", err)
log.Fatalf("Failed to bind to existing contract: %v", err)
func getRequiredEnv(key string) string {
value := os.Getenv(key)
if value == "" {
log.Fatalf("Required environment variable %s is not set", key)
}
return value
}
privateKey := getRequiredEnv("PRIVATE_KEY")
rpcURL := getRequiredEnv("RPC_URL")
taStoreAddress := getRequiredEnv("TA_STORE_CONTRACT_ADDRESS")
fr := framework.New(framework.WithCustomConfig(privateKey, rpcURL))
log.Printf("Using TA_STORE_CONTRACT_ADDRESS: %s", taStoreAddress)
taStoreContract, err := fr.Suave.BindToExistingContract(common.HexToAddress(taStoreAddress), testutil.TAStoreContractPath)
if err != nil {
log.Fatalf("Failed to bind to existing contract: %v", err)

@@ -156,7 +160,7 @@ func TestTransferAccountE2E(t *testing.T) {
AccountId: accountId,
Proof: transferSig,
},
To: tc.to,
Address: tc.to,
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Use proper Ethereum address format

Using the public key's X coordinate as an address is incorrect. Convert public keys to Ethereum addresses using crypto.PubkeyToAddress.

Apply this pattern throughout the test cases:

-Address: tc.to.PublicKey.X.String(),
+Address: crypto.PubkeyToAddress(tc.to.PublicKey).Hex(),

Also applies to: 379-379, 471-471, 632-632, 648-648

Comment on lines +94 to +108
TransferableAccountStore tas = new TransferableAccountStore();
SignatureVerifier.TimedSignature memory sig0 = generateTimedSignature(
uint64(block.timestamp + 86400), alice, ALICE_PRIVATE_KEY, tas.getNonce(alice), CREATE_ACCOUNT_FUNCTION_HASH
);

bytes memory encodedData = tas.createAccount(sig0);
bytes memory accountData = decodeEncodedData(encodedData);

(
SignatureVerifier.TimedSignature memory decodedTimedSignature,
ITransferableAccountStore.Account memory decodedAccount
) = abi.decode(accountData, (SignatureVerifier.TimedSignature, ITransferableAccountStore.Account));

assertEq(decodedTimedSignature.signature, sig.signature, "Signature should be same");
assertEq(decodedAccount.owner, sig.signer, "Owner should be alice");
assertEq(decodedTimedSignature.signature, sig0.signature, "Signature should be same");
assertEq(decodedAccount.owner, sig0.signer, "Owner should be alice");
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Extract common test setup into helper functions.

The test functions contain significant code duplication, particularly in the account creation and setup logic. Consider extracting these common patterns into helper functions.

function createTestAccount(
    TransferableAccountStore tas,
    address owner,
    uint256 privateKey
) internal returns (string memory accountId) {
    SignatureVerifier.TimedSignature memory sig = generateTimedSignature(
        uint64(block.timestamp + 86400),
        owner,
        privateKey,
        tas.getNonce(owner),
        CREATE_ACCOUNT_FUNCTION_HASH
    );
    bytes memory encodedData = tas.createAccount(sig);
    bytes memory accountData = decodeEncodedData(encodedData);
    (
        SignatureVerifier.TimedSignature memory decodedTimedSignature,
        ITransferableAccountStore.Account memory decodedAccount
    ) = abi.decode(accountData, (SignatureVerifier.TimedSignature, ITransferableAccountStore.Account));
    return tas.createAccountCallback(decodedTimedSignature, decodedAccount);
}

Also applies to: 148-171, 175-203, 210-242, 248-266, 269-293, 297-332, 335-359, 361-385, 388-428, 430-476, 478-503

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants