Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(rfq-relayer): wait for finality before proving #3062

Merged
merged 18 commits into from
Aug 30, 2024
Merged

Conversation

dwasse
Copy link
Collaborator

@dwasse dwasse commented Aug 26, 2024

Summary by CodeRabbit

  • New Features

    • Introduced new configuration fields, ProveConfirmations and FinalityConfirmations, for enhanced control over confirmation processes in RFQ operations.
    • Added functions to retrieve ProveConfirmations and FinalityConfirmations values for specific chain configurations.
    • Implemented a new function to retrieve the relay block number for quote requests.
  • Improvements

    • Enhanced the proof submission process to ensure sufficient confirmations are received before proceeding, improving reliability.
    • Added verification for finalized transactions in the processing logic, enhancing transaction handling robustness.
    • Incorporated a block number field in transaction models to improve tracking of blockchain-related events.

Copy link
Contributor

coderabbitai bot commented Aug 26, 2024

Warning

Rate limit exceeded

@dwasse has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 2 minutes and 3 seconds before requesting another review.

How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

Commits

Files that changed from the base of the PR and between 978bcf2 and db7f9fd.

Walkthrough

The changes introduce new configuration fields, ProveConfirmations and FinalityConfirmations, to the ChainConfig struct, enhancing configuration capabilities. New functions, GetProveConfirmations and GetFinalityConfirmations, are added for retrieving these values. Modifications to the handleRelayCompleted method ensure sufficient confirmations are checked before proof submission, while a new verification step in the handleProveCalled method guarantees that only finalized transactions are processed. Additionally, BlockNumber fields are added to relevant structs for improved tracking.

Changes

Files Change Summary
services/rfq/relayer/relconfig/config.go, services/rfq/relayer/relconfig/getters.go Added ProveConfirmations and FinalityConfirmations fields to ChainConfig and created corresponding getter functions.
services/rfq/relayer/service/handlers.go Updated handleRelayCompleted method to check for sufficient confirmations before submitting proof and added getRelayBlockNumber function.
services/rfq/guard/service/handlers.go Added verification in handleProveCalled to ensure only finalized transactions are processed.
services/rfq/guard/guarddb/base/model.go, services/rfq/guard/guarddb/db.go Introduced BlockNumber field to PendingProvenModel and PendingProven structs, updating relevant methods.

Possibly related issues

  • Fast Bridge Canonical Guard #2833: The changes enhance the RFQ Guard functionality, aligning with the objective of ensuring transaction integrity and monitoring prove() calls.

Poem

In the meadow, hop and play,
New changes brighten up the day!
Configs added, confirmations too,
A happy handler, all brand new!
With every hop, we leap so high,
Celebrating changes, oh my, oh my! 🐇✨


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>.
    • 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 generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @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.

@github-actions github-actions bot added go Pull requests that update Go code size/xs labels Aug 26, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 7793703 and f00f3c8.

Files selected for processing (4)
  • services/rfq/relayer/relconfig/config.go (1 hunks)
  • services/rfq/relayer/relconfig/getters.go (1 hunks)
  • services/rfq/relayer/service/handlers.go (1 hunks)
  • services/rfq/relayer/service/statushandler.go (3 hunks)
Additional comments not posted (4)
services/rfq/relayer/service/statushandler.go (2)

58-59: LGTM!

The addition of the cfg field to the QuoteRequestHandler struct is a good practice for managing configuration settings within the handler.

The code changes are approved.


94-94: LGTM!

The initialization of the cfg field in the requestToHandler function ensures that the handler has access to the relayer configuration settings.

The code changes are approved.

services/rfq/relayer/relconfig/config.go (1)

77-78: LGTM!

The addition of the ProveConfirmations field to the ChainConfig struct enhances the configuration capabilities by allowing for more granular control over the confirmation process.

The code changes are approved.

services/rfq/relayer/service/handlers.go (1)

381-401: LGTM!

The modifications to the handleRelayCompleted method enhance its functionality by ensuring that sufficient confirmations have been received before proceeding with the proof submission. This change improves the reliability of the proof submission process.

The code changes are approved.

Comment on lines 219 to 230
func (c Config) GetProveConfirmations(chainID int) (value uint64, err error) {
rawValue, err := c.getChainConfigValue(chainID, "ProveConfirmations")
if err != nil {
return value, err
}

value, ok := rawValue.(uint64)
if !ok {
return value, fmt.Errorf("failed to cast ProveConfirmations to int")
}
return value, nil
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Add unit tests for the new function.

The function should include unit tests to ensure its correctness.

Do you want me to generate the unit testing code or open a GitHub issue to track this task?


Correct the error message in the type assertion failure.

The error message should mention uint64 instead of int.

- return value, fmt.Errorf("failed to cast ProveConfirmations to int")
+ return value, fmt.Errorf("failed to cast ProveConfirmations to uint64")
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 (c Config) GetProveConfirmations(chainID int) (value uint64, err error) {
rawValue, err := c.getChainConfigValue(chainID, "ProveConfirmations")
if err != nil {
return value, err
}
value, ok := rawValue.(uint64)
if !ok {
return value, fmt.Errorf("failed to cast ProveConfirmations to int")
}
return value, nil
}
func (c Config) GetProveConfirmations(chainID int) (value uint64, err error) {
rawValue, err := c.getChainConfigValue(chainID, "ProveConfirmations")
if err != nil {
return value, err
}
value, ok := rawValue.(uint64)
if !ok {
return value, fmt.Errorf("failed to cast ProveConfirmations to uint64")
}
return value, nil
}

Copy link

codecov bot commented Aug 26, 2024

Codecov Report

Attention: Patch coverage is 0% with 84 lines in your changes missing coverage. Please review.

Project coverage is 30.14768%. Comparing base (a6e1781) to head (db7f9fd).
Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
services/rfq/relayer/service/handlers.go 0.00000% 37 Missing ⚠️
services/rfq/guard/service/handlers.go 0.00000% 33 Missing ⚠️
services/rfq/relayer/relconfig/getters.go 0.00000% 10 Missing ⚠️
services/rfq/guard/guarddb/base/model.go 0.00000% 2 Missing ⚠️
services/rfq/guard/guardconfig/config.go 0.00000% 1 Missing ⚠️
services/rfq/relayer/service/statushandler.go 0.00000% 1 Missing ⚠️
Additional details and impacted files
@@                 Coverage Diff                 @@
##              master       #3062         +/-   ##
===================================================
+ Coverage   23.06899%   30.14768%   +7.07869%     
===================================================
  Files            193         439        +246     
  Lines          11639       28304      +16665     
  Branches          82          82                 
===================================================
+ Hits            2685        8533       +5848     
- Misses          8712       18980      +10268     
- Partials         242         791        +549     
Flag Coverage Δ
opbot 0.49906% <ø> (ø)
packages 90.56974% <ø> (ø)
promexporter 6.92368% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link

cloudflare-workers-and-pages bot commented Aug 26, 2024

Deploying sanguine-fe with  Cloudflare Pages  Cloudflare Pages

Latest commit: db7f9fd
Status: ✅  Deploy successful!
Preview URL: https://e2c074f1.sanguine-fe.pages.dev
Branch Preview URL: https://feat-prove-finality.sanguine-fe.pages.dev

View logs

@github-actions github-actions bot added size/s and removed size/xs labels Aug 26, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between f00f3c8 and a5286c8.

Files selected for processing (5)
  • services/rfq/guard/guardconfig/config.go (1 hunks)
  • services/rfq/guard/service/handlers.go (2 hunks)
  • services/rfq/relayer/relconfig/config.go (1 hunks)
  • services/rfq/relayer/relconfig/getters.go (1 hunks)
  • services/rfq/relayer/service/handlers.go (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • services/rfq/relayer/relconfig/config.go
Additional context used
GitHub Check: Lint (services/rfq)
services/rfq/guard/service/handlers.go

[failure] 277-277:
SA5011: possible nil pointer dereference (staticcheck)


[failure] 286-286:
SA5011(related information): this check suggests that the pointer can be nil (staticcheck)


[failure] 282-282:
SA5011: possible nil pointer dereference (staticcheck)

GitHub Check: codecov/patch
services/rfq/relayer/service/handlers.go

[warning] 381-387: services/rfq/relayer/service/handlers.go#L381-L387
Added lines #L381 - L387 were not covered by tests


[warning] 389-400: services/rfq/relayer/service/handlers.go#L389-L400
Added lines #L389 - L400 were not covered by tests

services/rfq/relayer/relconfig/getters.go

[warning] 221-223: services/rfq/relayer/relconfig/getters.go#L221-L223
Added lines #L221 - L223 were not covered by tests


[warning] 225-226: services/rfq/relayer/relconfig/getters.go#L225-L226
Added lines #L225 - L226 were not covered by tests


[warning] 228-229: services/rfq/relayer/relconfig/getters.go#L228-L229
Added lines #L228 - L229 were not covered by tests

Additional comments not posted (2)
services/rfq/guard/guardconfig/config.go (1)

119-119: LGTM! But verify the function usage in the codebase.

The change aligns the confirmation mechanism with finality rather than a simple confirmation count. Ensure that all function calls to NewGuardConfigFromRelayer are updated accordingly.

The code changes are approved.

Run the following script to verify the function usage:

Verification successful

Function usage is consistent with the new logic.

The function NewGuardConfigFromRelayer is used correctly with the updated FinalityConfirmations logic in the following files:

  • services/rfq/relayer/service/relayer.go
  • services/rfq/e2e/setup_test.go

No issues were found with the function usage.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify all function calls to `NewGuardConfigFromRelayer` match the new logic.

# Test: Search for the function usage. Expect: Only occurrences of the new logic.
rg --type go -A 5 $'NewGuardConfigFromRelayer'

Length of output: 1557

services/rfq/guard/service/handlers.go (1)

118-126: LGTM! But verify the function usage in the codebase.

The change enhances the robustness of the transaction handling by ensuring that only finalized transactions are processed further. Ensure that all function calls to handleProveCalled are updated accordingly.

The code changes are approved.

Run the following script to verify the function usage:

Verification successful

Function usage verified successfully.

The function handleProveCalled is used in a manner consistent with the new logic introduced. The single call to this function in services/rfq/guard/service/guard.go handles errors appropriately, ensuring robustness in transaction handling. No further updates are needed.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify all function calls to `handleProveCalled` match the new logic.

# Test: Search for the function usage. Expect: Only occurrences of the new logic.
rg --type go -A 5 $'handleProveCalled'

Length of output: 999

Comment on lines 256 to 287
// isFinalized checks if a transaction is finalized versus the configured confirmations threshold.
func (g *Guard) isFinalized(ctx context.Context, txHash common.Hash, chainID int) (bool, error) {
span := trace.SpanFromContext(ctx)

client, err := g.client.GetChainClient(ctx, chainID)
if err != nil {
return false, fmt.Errorf("could not get chain client: %w", err)
}
receipt, err := client.TransactionReceipt(ctx, txHash)
if err != nil {
return false, fmt.Errorf("could not get receipt: %w", err)
}
currentBlockNumber, err := client.BlockNumber(ctx)
if err != nil {
return false, fmt.Errorf("could not get block number: %w", err)
}

chainCfg, ok := g.cfg.Chains[chainID]
if !ok {
return false, fmt.Errorf("could not get chain config for chain %d", chainID)
}
threshBlockNumber := uint64(receipt.BlockNumber.Int64()) + chainCfg.Confirmations
span.SetAttributes(
attribute.String("tx_hash", txHash.Hex()),
attribute.Int("chain_id", chainID),
attribute.Int64("current_block_number", int64(currentBlockNumber)),
attribute.Int64("receipt_block_number", receipt.BlockNumber.Int64()),
attribute.Int("confirmations", int(chainCfg.Confirmations)),
)

return receipt != nil && currentBlockNumber >= threshBlockNumber, nil
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Fix potential nil pointer dereference.

The function isFinalized has a potential issue with nil pointer dereference. Ensure that the receipt is checked for nil before accessing its fields.

Apply this diff to fix the potential nil pointer dereference:

 func (g *Guard) isFinalized(ctx context.Context, txHash common.Hash, chainID int) (bool, error) {
	span := trace.SpanFromContext(ctx)

	client, err := g.client.GetChainClient(ctx, chainID)
	if err != nil {
		return false, fmt.Errorf("could not get chain client: %w", err)
	}
	receipt, err := client.TransactionReceipt(ctx, txHash)
	if err != nil {
		return false, fmt.Errorf("could not get receipt: %w", err)
	}
+	if receipt == nil {
+		return false, fmt.Errorf("receipt is nil")
+	}
	currentBlockNumber, err := client.BlockNumber(ctx)
	if err != nil {
		return false, fmt.Errorf("could not get block number: %w", err)
	}

	chainCfg, ok := g.cfg.Chains[chainID]
	if !ok {
		return false, fmt.Errorf("could not get chain config for chain %d", chainID)
	}
	threshBlockNumber := uint64(receipt.BlockNumber.Int64()) + chainCfg.Confirmations
	span.SetAttributes(
		attribute.String("tx_hash", txHash.Hex()),
		attribute.Int("chain_id", chainID),
		attribute.Int64("current_block_number", int64(currentBlockNumber)),
		attribute.Int64("receipt_block_number", receipt.BlockNumber.Int64()),
		attribute.Int("confirmations", int(chainCfg.Confirmations)),
	)

	return receipt != nil && currentBlockNumber >= threshBlockNumber, nil
}
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
// isFinalized checks if a transaction is finalized versus the configured confirmations threshold.
func (g *Guard) isFinalized(ctx context.Context, txHash common.Hash, chainID int) (bool, error) {
span := trace.SpanFromContext(ctx)
client, err := g.client.GetChainClient(ctx, chainID)
if err != nil {
return false, fmt.Errorf("could not get chain client: %w", err)
}
receipt, err := client.TransactionReceipt(ctx, txHash)
if err != nil {
return false, fmt.Errorf("could not get receipt: %w", err)
}
currentBlockNumber, err := client.BlockNumber(ctx)
if err != nil {
return false, fmt.Errorf("could not get block number: %w", err)
}
chainCfg, ok := g.cfg.Chains[chainID]
if !ok {
return false, fmt.Errorf("could not get chain config for chain %d", chainID)
}
threshBlockNumber := uint64(receipt.BlockNumber.Int64()) + chainCfg.Confirmations
span.SetAttributes(
attribute.String("tx_hash", txHash.Hex()),
attribute.Int("chain_id", chainID),
attribute.Int64("current_block_number", int64(currentBlockNumber)),
attribute.Int64("receipt_block_number", receipt.BlockNumber.Int64()),
attribute.Int("confirmations", int(chainCfg.Confirmations)),
)
return receipt != nil && currentBlockNumber >= threshBlockNumber, nil
}
func (g *Guard) isFinalized(ctx context.Context, txHash common.Hash, chainID int) (bool, error) {
span := trace.SpanFromContext(ctx)
client, err := g.client.GetChainClient(ctx, chainID)
if err != nil {
return false, fmt.Errorf("could not get chain client: %w", err)
}
receipt, err := client.TransactionReceipt(ctx, txHash)
if err != nil {
return false, fmt.Errorf("could not get receipt: %w", err)
}
if receipt == nil {
return false, fmt.Errorf("receipt is nil")
}
currentBlockNumber, err := client.BlockNumber(ctx)
if err != nil {
return false, fmt.Errorf("could not get block number: %w", err)
}
chainCfg, ok := g.cfg.Chains[chainID]
if !ok {
return false, fmt.Errorf("could not get chain config for chain %d", chainID)
}
threshBlockNumber := uint64(receipt.BlockNumber.Int64()) + chainCfg.Confirmations
span.SetAttributes(
attribute.String("tx_hash", txHash.Hex()),
attribute.Int("chain_id", chainID),
attribute.Int64("current_block_number", int64(currentBlockNumber)),
attribute.Int64("receipt_block_number", receipt.BlockNumber.Int64()),
attribute.Int("confirmations", int(chainCfg.Confirmations)),
)
return receipt != nil && currentBlockNumber >= threshBlockNumber, nil
}
Tools
GitHub Check: Lint (services/rfq)

[failure] 277-277:
SA5011: possible nil pointer dereference (staticcheck)


[failure] 286-286:
SA5011(related information): this check suggests that the pointer can be nil (staticcheck)


[failure] 282-282:
SA5011: possible nil pointer dereference (staticcheck)

Comment on lines 381 to 400
func (q *QuoteRequestHandler) handleRelayCompleted(ctx context.Context, span trace.Span, request reldb.QuoteRequest) (err error) {
// first, ensure that enough confirmations have passed before proving
receipt, err := q.Dest.Client.TransactionReceipt(ctx, request.DestTxHash)
if err != nil {
return fmt.Errorf("could not get transaction receipt: %w", err)
}
currentBlockNumber := q.Origin.LatestBlock()
proveConfirmations, err := q.cfg.GetFinalityConfirmations(int(q.Dest.ChainID))
if err != nil {
return fmt.Errorf("could not get prove confirmations: %w", err)
}
span.SetAttributes(
attribute.Int("current_block_number", int(currentBlockNumber)),
attribute.Int("dest_block_number", int(receipt.BlockNumber.Int64())),
attribute.Int("prove_confirmations", int(proveConfirmations)),
)
if currentBlockNumber < request.BlockNumber+proveConfirmations {
span.AddEvent("not enough confirmations")
return nil
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Reminder: Add tests.

The added lines are not covered by tests. Ensure that the new logic is adequately tested.

Do you want me to generate the unit testing code or open a GitHub issue to track this task?

Tools
GitHub Check: codecov/patch

[warning] 381-387: services/rfq/relayer/service/handlers.go#L381-L387
Added lines #L381 - L387 were not covered by tests


[warning] 389-400: services/rfq/relayer/service/handlers.go#L389-L400
Added lines #L389 - L400 were not covered by tests

Comment on lines +219 to +230
func (c Config) GetFinalityConfirmations(chainID int) (value uint64, err error) {
rawValue, err := c.getChainConfigValue(chainID, "FinalityConfirmations")
if err != nil {
return value, err
}

value, ok := rawValue.(uint64)
if !ok {
return value, fmt.Errorf("failed to cast FinalityConfirmations to int")
}
return value, nil
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Add unit tests for the new function.

The function should include unit tests to ensure its correctness.

Do you want me to generate the unit testing code or open a GitHub issue to track this task?

Tools
GitHub Check: codecov/patch

[warning] 221-223: services/rfq/relayer/relconfig/getters.go#L221-L223
Added lines #L221 - L223 were not covered by tests


[warning] 225-226: services/rfq/relayer/relconfig/getters.go#L225-L226
Added lines #L225 - L226 were not covered by tests


[warning] 228-229: services/rfq/relayer/relconfig/getters.go#L228-L229
Added lines #L228 - L229 were not covered by tests


Correct the error message in the type assertion failure.

The error message should mention uint64 instead of int.

- return value, fmt.Errorf("failed to cast FinalityConfirmations to int")
+ return value, fmt.Errorf("failed to cast FinalityConfirmations to uint64")
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 (c Config) GetFinalityConfirmations(chainID int) (value uint64, err error) {
rawValue, err := c.getChainConfigValue(chainID, "FinalityConfirmations")
if err != nil {
return value, err
}
value, ok := rawValue.(uint64)
if !ok {
return value, fmt.Errorf("failed to cast FinalityConfirmations to int")
}
return value, nil
}
func (c Config) GetFinalityConfirmations(chainID int) (value uint64, err error) {
rawValue, err := c.getChainConfigValue(chainID, "FinalityConfirmations")
if err != nil {
return value, err
}
value, ok := rawValue.(uint64)
if !ok {
return value, fmt.Errorf("failed to cast FinalityConfirmations to uint64")
}
return value, nil
}
Tools
GitHub Check: codecov/patch

[warning] 221-223: services/rfq/relayer/relconfig/getters.go#L221-L223
Added lines #L221 - L223 were not covered by tests


[warning] 225-226: services/rfq/relayer/relconfig/getters.go#L225-L226
Added lines #L225 - L226 were not covered by tests


[warning] 228-229: services/rfq/relayer/relconfig/getters.go#L228-L229
Added lines #L228 - L229 were not covered by tests

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between a5286c8 and 108c64d.

Files selected for processing (3)
  • services/rfq/guard/guarddb/base/model.go (3 hunks)
  • services/rfq/guard/guarddb/db.go (1 hunks)
  • services/rfq/guard/service/handlers.go (3 hunks)
Additional comments not posted (7)
services/rfq/guard/guarddb/db.go (1)

67-67: LGTM!

The addition of the BlockNumber field enhances the struct by allowing it to store the block number associated with a pending transaction.

The code changes are approved.

services/rfq/guard/guarddb/base/model.go (3)

45-46: LGTM!

The addition of the BlockNumber field enhances the struct by allowing it to store the block number associated with an event.

The code changes are approved.


57-57: LGTM!

The function correctly populates the new BlockNumber field from the proven parameter.

The code changes are approved.


79-79: LGTM!

The function correctly includes the BlockNumber when converting the PendingProvenModel back to a guarddb.PendingProven object.

The code changes are approved.

services/rfq/guard/service/handlers.go (3)

85-85: LGTM!

The function correctly stores the BlockNumber from the event, enhancing the tracking of transaction states.

The code changes are approved.


119-128: LGTM!

The function correctly includes a verification step to check if a transaction is finalized before proceeding, ensuring that only finalized transactions are processed further.

The code changes are approved.


257-284: LGTM!

The function correctly encapsulates the logic for checking if a transaction is finalized versus the configured confirmations threshold.

The code changes are approved.

return nil
}

// relay has been finalized, it's time to go back to the origin chain and try to prove
Copy link
Collaborator

Choose a reason for hiding this comment

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

@dwasse we need to do a check similar to Guard's isProveValid here to handle the case where our relay tx was reorged.

In the event where we submitted a tx, witnessed a BridgeRelayed event, and later on this tx was reorged and ended up being reverted, we need a way for the Relayer to mark the tx as RelayRaceLost here (I'm not sure if we can safely assume that we will index the correct event with another relayer before that).

The current code will still get a valid receipt for DestTxHash, it's just the receipt will not have a corresponding BridgeRelayed event there.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 108c64d and 3524d13.

Files selected for processing (1)
  • services/rfq/relayer/service/handlers.go (2 hunks)
Additional comments not posted (8)
services/rfq/relayer/service/handlers.go (8)

381-381: Ensure sufficient confirmations before proving.

The function now includes logic to wait for sufficient confirmations before proving the transaction.

The code changes are approved.


382-385: Retrieve relay block number.

The function correctly retrieves the relay block number using getRelayBlockNumber.

The code changes are approved.


387-400: Retrieve current block number and prove confirmations.

The function correctly retrieves the current block number and prove confirmations and performs the necessary check.

The code changes are approved.


Line range hint 402-419: Submit proof transaction.

The function correctly submits the proof transaction if the necessary conditions are met.

The code changes are approved.


422-422: New function: getRelayBlockNumber.

The function retrieves the relay block number from the transaction receipt.

The code changes are approved.


423-427: Fetch transaction receipt.

The function correctly fetches the transaction receipt for the destination transaction hash.

The code changes are approved.


428-445: Parse transaction receipt logs.

The function correctly parses the transaction receipt logs to find the Relayed event.

The code changes are approved.


448-449: Handle missing Relayed event.

The function correctly handles the case where the Relayed event is not found in the transaction receipt logs.

The code changes are approved.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 3524d13 and 19dd299.

Files selected for processing (1)
  • services/rfq/relayer/service/handlers.go (2 hunks)

Comment on lines 381 to 401
func (q *QuoteRequestHandler) handleRelayCompleted(ctx context.Context, span trace.Span, request reldb.QuoteRequest) (err error) {
relayBlockNumber, err := q.getRelayBlockNumber(ctx, request)
if err != nil {
return fmt.Errorf("could not get relay block number: %w", err)
}
currentBlockNumber := q.Origin.LatestBlock()
proveConfirmations, err := q.cfg.GetFinalityConfirmations(int(q.Dest.ChainID))
if err != nil {
return fmt.Errorf("could not get prove confirmations: %w", err)
}

span.SetAttributes(
attribute.Int("current_block_number", int(currentBlockNumber)),
attribute.Int("relay_block_number", int(relayBlockNumber)),
attribute.Int("prove_confirmations", int(proveConfirmations)),
)
if currentBlockNumber < relayBlockNumber+proveConfirmations {
span.AddEvent("not enough confirmations")
return nil
}

Copy link
Contributor

Choose a reason for hiding this comment

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

LGTM! Ensure tests cover the new logic.

The changes improve the reliability of the proof submission process by ensuring that it only occurs when the blockchain state is sufficiently advanced. Ensure that the new logic is adequately tested.

Do you want me to generate the unit testing code or open a GitHub issue to track this task?

Comment on lines 422 to 450
// getRelayBlockNumber fetches the block number of the relay transaction for a given quote request.
func (q *QuoteRequestHandler) getRelayBlockNumber(ctx context.Context, request reldb.QuoteRequest) (blockNumber uint64, err error) {
// fetch the transaction receipt for corresponding tx hash
receipt, err := q.Dest.Client.TransactionReceipt(ctx, request.DestTxHash)
if err != nil {
return blockNumber, fmt.Errorf("could not get transaction receipt: %w", err)
}
parser, err := fastbridge.NewParser(q.Dest.Bridge.Address())
if err != nil {
return blockNumber, fmt.Errorf("could not create parser: %w", err)
}

// check that a Relayed event was emitted
for _, log := range receipt.Logs {
if log == nil {
continue
}
_, parsedEvent, ok := parser.ParseEvent(*log)
if !ok {
continue
}
_, ok = parsedEvent.(*fastbridge.FastBridgeBridgeRelayed)
if ok {
return receipt.BlockNumber.Uint64(), nil
}
}

return blockNumber, fmt.Errorf("relayed event not found for dest tx hash: %s", request.DestTxHash.Hex())
}
Copy link
Contributor

Choose a reason for hiding this comment

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

LGTM! Consider adding error handling for potential reorgs.

The function encapsulates the logic for fetching the block number of the relay transaction, improving code modularity and readability. Consider adding error handling for potential reorgs to ensure robustness.

Add error handling for potential reorgs.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 19dd299 and 6d41b64.

Files selected for processing (2)
  • services/rfq/relayer/reldb/base/quote.go (1 hunks)
  • services/rfq/relayer/service/handlers.go (2 hunks)
Additional context used
GitHub Check: codecov/patch
services/rfq/relayer/service/handlers.go

[warning] 381-381: services/rfq/relayer/service/handlers.go#L381
Added line #L381 was not covered by tests


[warning] 383-384: services/rfq/relayer/service/handlers.go#L383-L384
Added lines #L383 - L384 were not covered by tests


[warning] 391-392: services/rfq/relayer/service/handlers.go#L391-L392
Added lines #L391 - L392 were not covered by tests


[warning] 400-409: services/rfq/relayer/service/handlers.go#L400-L409
Added lines #L400 - L409 were not covered by tests


[warning] 430-432: services/rfq/relayer/service/handlers.go#L430-L432
Added lines #L430 - L432 were not covered by tests


[warning] 441-441: services/rfq/relayer/service/handlers.go#L441
Added line #L441 was not covered by tests


[warning] 443-445: services/rfq/relayer/service/handlers.go#L443-L445
Added lines #L443 - L445 were not covered by tests


[warning] 449-458: services/rfq/relayer/service/handlers.go#L449-L458
Added lines #L449 - L458 were not covered by tests


[warning] 461-463: services/rfq/relayer/service/handlers.go#L461-L463
Added lines #L461 - L463 were not covered by tests


[warning] 465-466: services/rfq/relayer/service/handlers.go#L465-L466
Added lines #L465 - L466 were not covered by tests

GitHub Check: Lint (services/rfq)
services/rfq/relayer/service/handlers.go

[failure] 453-453:
Duplicate words (get) found (dupword)

Additional comments not posted (1)
services/rfq/relayer/reldb/base/quote.go (1)

136-136: Approve addition of new state transition.

The inclusion of RelayRaceLost as a valid state transition in isValidStateTransition is logical and enhances the system's ability to handle different outcomes of the relay process.

However, verify that this new state is integrated correctly across all relevant parts of the system.

Run the following script to verify the handling of the RelayRaceLost state:

Verification successful

RelayRaceLost state is integrated correctly across the system.

The RelayRaceLost state is handled in various parts of the codebase, including updates to quote request statuses and specific handling logic in service handlers and chain indexers. This confirms that the state is integrated as intended.

  • Files Handling RelayRaceLost:
    • services/rfq/relayer/service/handlers.go
    • services/rfq/relayer/reldb/db.go
    • services/rfq/relayer/reldb/base/quote.go
    • services/rfq/relayer/reldb/quoterequeststatus_string.go
    • services/rfq/relayer/service/chainindexer.go
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that the `RelayRaceLost` state is handled correctly in all relevant parts of the system.

# Test: Search for handling of `RelayRaceLost`. Expect: Handling logic in relevant parts of the system.
rg --type python -A 5 $'RelayRaceLost'

Length of output: 68


Script:

#!/bin/bash
# Description: Verify that the `RelayRaceLost` state is handled correctly in all relevant parts of the system.

# Test: Search for handling of `RelayRaceLost`. Expect: Handling logic in relevant parts of the system.
rg -A 5 'RelayRaceLost'

Length of output: 4541

Comment on lines +381 to +409
func (q *QuoteRequestHandler) handleRelayCompleted(ctx context.Context, span trace.Span, request reldb.QuoteRequest) (err error) {
// fetch the block of the relay transaction to confirm that it has been finalized
relayBlockNumber, err := q.getRelayBlockNumber(ctx, request)
if err != nil {
// relay tx must have gotten reorged; mark as RelayRaceLost
span.SetAttributes(attribute.String("receipt_error", err.Error()))
err = q.db.UpdateQuoteRequestStatus(ctx, request.TransactionID, reldb.RelayRaceLost, nil)
if err != nil {
return fmt.Errorf("could not update request status: %w", err)
}
return fmt.Errorf("could not get relay block number: %w", err)
}

currentBlockNumber := q.Origin.LatestBlock()
proveConfirmations, err := q.cfg.GetFinalityConfirmations(int(q.Dest.ChainID))
if err != nil {
return fmt.Errorf("could not get prove confirmations: %w", err)
}

span.SetAttributes(
attribute.Int("current_block_number", int(currentBlockNumber)),
attribute.Int("relay_block_number", int(relayBlockNumber)),
attribute.Int("prove_confirmations", int(proveConfirmations)),
)
if currentBlockNumber < relayBlockNumber+proveConfirmations {
span.AddEvent("not enough confirmations")
return nil
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Ensure sufficient test coverage for new logic in handleRelayCompleted.

The changes in handleRelayCompleted introduce significant logic related to transaction finality checks. However, static analysis indicates that these lines are not covered by tests. Ensuring that new logic is adequately tested is crucial for maintaining the reliability of the system, especially given the critical nature of blockchain transaction handling.

Please add unit tests to cover the new logic introduced in this method. If you need assistance with this, I can help generate the unit testing code or open a GitHub issue to track this task.

Tools
GitHub Check: codecov/patch

[warning] 381-381: services/rfq/relayer/service/handlers.go#L381
Added line #L381 was not covered by tests


[warning] 383-384: services/rfq/relayer/service/handlers.go#L383-L384
Added lines #L383 - L384 were not covered by tests


[warning] 391-392: services/rfq/relayer/service/handlers.go#L391-L392
Added lines #L391 - L392 were not covered by tests


[warning] 400-409: services/rfq/relayer/service/handlers.go#L400-L409
Added lines #L400 - L409 were not covered by tests

Comment on lines 430 to 465
// getRelayBlockNumber fetches the block number of the relay transaction for a given quote request.
func (q *QuoteRequestHandler) getRelayBlockNumber(ctx context.Context, request reldb.QuoteRequest) (blockNumber uint64, err error) {
// fetch the transaction receipt for corresponding tx hash
var receipt *types.Receipt
err = retry.WithBackoff(ctx, func(context.Context) error {
receipt, err = q.Dest.Client.TransactionReceipt(ctx, request.DestTxHash)
if err != nil {
return fmt.Errorf("could not get transaction receipt: %w", err)
}
return nil
}, retry.WithMaxTotalTime(15*time.Second))
if err != nil {
return blockNumber, fmt.Errorf("could not get get receipt: %w", err)
}
parser, err := fastbridge.NewParser(q.Dest.Bridge.Address())
if err != nil {
return blockNumber, fmt.Errorf("could not create parser: %w", err)
}

// check that a Relayed event was emitted
for _, log := range receipt.Logs {
if log == nil {
continue
}
_, parsedEvent, ok := parser.ParseEvent(*log)
if !ok {
continue
}
_, ok = parsedEvent.(*fastbridge.FastBridgeBridgeRelayed)
if ok {
return receipt.BlockNumber.Uint64(), nil
}
}

return blockNumber, fmt.Errorf("relayed event not found for dest tx hash: %s", request.DestTxHash.Hex())
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Refactor getRelayBlockNumber to handle errors more gracefully and ensure event parsing is robust.

The method getRelayBlockNumber fetches the block number of a relay transaction, which is crucial for ensuring that the transaction has been finalized. However, there are several areas where the error handling and event parsing could be improved:

  1. Error Handling: The method retries fetching the transaction receipt but does not handle potential continuous failures beyond the retry limit. This could lead to unhandled errors in critical transaction handling logic.
  2. Event Parsing: The loop checking for a Relayed event does not account for possible anomalies like missing or malformed logs.

Consider implementing more comprehensive error handling strategies and robust log parsing to ensure the reliability of this method. Here's a proposed refactor for better error handling and event parsing:

func (q *QuoteRequestHandler) getRelayBlockNumber(ctx context.Context, request reldb.QuoteRequest) (blockNumber uint64, err error) {
    var receipt *types.Receipt
    err = retry.WithBackoff(ctx, func(context.Context) error {
        receipt, err = q.Dest.Client.TransactionReceipt(ctx, request.DestTxHash)
        if err != nil {
            return fmt.Errorf("could not get transaction receipt: %w", err)
        }
        return nil
    }, retry.WithMaxTotalTime(15*time.Second))
    if err != nil {
        return blockNumber, fmt.Errorf("could not get receipt after retries: %w", err)
    }
    parser, err := fastbridge.NewParser(q.Dest.Bridge.Address())
    if err != nil {
        return blockNumber, fmt.Errorf("could not create parser: %w", err)
    }
    found := false
    for _, log := range receipt.Logs {
        if log == nil {
            continue
        }
        _, parsedEvent, ok := parser.ParseEvent(*log)
        if ok {
            if _, ok := parsedEvent.(*fastbridge.FastBridgeBridgeRelayed); ok {
                found = true
                blockNumber = receipt.BlockNumber.Uint64()
                break
            }
        }
    }
    if !found {
        return blockNumber, fmt.Errorf("relayed event not found for dest tx hash: %s", request.DestTxHash.Hex())
    }
    return blockNumber, nil
}

This refactor includes a check to ensure all retries are exhausted before returning an error and improves clarity in event parsing.

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
// getRelayBlockNumber fetches the block number of the relay transaction for a given quote request.
func (q *QuoteRequestHandler) getRelayBlockNumber(ctx context.Context, request reldb.QuoteRequest) (blockNumber uint64, err error) {
// fetch the transaction receipt for corresponding tx hash
var receipt *types.Receipt
err = retry.WithBackoff(ctx, func(context.Context) error {
receipt, err = q.Dest.Client.TransactionReceipt(ctx, request.DestTxHash)
if err != nil {
return fmt.Errorf("could not get transaction receipt: %w", err)
}
return nil
}, retry.WithMaxTotalTime(15*time.Second))
if err != nil {
return blockNumber, fmt.Errorf("could not get get receipt: %w", err)
}
parser, err := fastbridge.NewParser(q.Dest.Bridge.Address())
if err != nil {
return blockNumber, fmt.Errorf("could not create parser: %w", err)
}
// check that a Relayed event was emitted
for _, log := range receipt.Logs {
if log == nil {
continue
}
_, parsedEvent, ok := parser.ParseEvent(*log)
if !ok {
continue
}
_, ok = parsedEvent.(*fastbridge.FastBridgeBridgeRelayed)
if ok {
return receipt.BlockNumber.Uint64(), nil
}
}
return blockNumber, fmt.Errorf("relayed event not found for dest tx hash: %s", request.DestTxHash.Hex())
}
func (q *QuoteRequestHandler) getRelayBlockNumber(ctx context.Context, request reldb.QuoteRequest) (blockNumber uint64, err error) {
var receipt *types.Receipt
err = retry.WithBackoff(ctx, func(context.Context) error {
receipt, err = q.Dest.Client.TransactionReceipt(ctx, request.DestTxHash)
if err != nil {
return fmt.Errorf("could not get transaction receipt: %w", err)
}
return nil
}, retry.WithMaxTotalTime(15*time.Second))
if err != nil {
return blockNumber, fmt.Errorf("could not get receipt after retries: %w", err)
}
parser, err := fastbridge.NewParser(q.Dest.Bridge.Address())
if err != nil {
return blockNumber, fmt.Errorf("could not create parser: %w", err)
}
found := false
for _, log := range receipt.Logs {
if log == nil {
continue
}
_, parsedEvent, ok := parser.ParseEvent(*log)
if ok {
if _, ok := parsedEvent.(*fastbridge.FastBridgeBridgeRelayed); ok {
found = true
blockNumber = receipt.BlockNumber.Uint64()
break
}
}
}
if !found {
return blockNumber, fmt.Errorf("relayed event not found for dest tx hash: %s", request.DestTxHash.Hex())
}
return blockNumber, nil
}
Tools
GitHub Check: codecov/patch

[warning] 430-432: services/rfq/relayer/service/handlers.go#L430-L432
Added lines #L430 - L432 were not covered by tests


[warning] 441-441: services/rfq/relayer/service/handlers.go#L441
Added line #L441 was not covered by tests


[warning] 443-445: services/rfq/relayer/service/handlers.go#L443-L445
Added lines #L443 - L445 were not covered by tests


[warning] 449-458: services/rfq/relayer/service/handlers.go#L449-L458
Added lines #L449 - L458 were not covered by tests


[warning] 461-463: services/rfq/relayer/service/handlers.go#L461-L463
Added lines #L461 - L463 were not covered by tests

GitHub Check: Lint (services/rfq)

[failure] 453-453:
Duplicate words (get) found (dupword)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 6d41b64 and 978bcf2.

Files selected for processing (1)
  • services/rfq/relayer/service/handlers.go (2 hunks)
Files skipped from review as they are similar to previous changes (1)
  • services/rfq/relayer/service/handlers.go

Copy link

codecov bot commented Aug 30, 2024

Bundle Report

Changes will decrease total bundle size by 10.32MB ⬇️

Bundle name Size Change
widget-cjs-esm 281.92kB 0 bytes
synapse-interface-server-cjs 1.33MB 145.66kB ⬇️
sdk-router-@synapsecns/sdk-router-esm 254.97kB 0 bytes
sdk-router-@synapsecns/sdk-router-cjs 527.05kB 409.81kB ⬆️
synapse-interface-edge-server-array-push 83 bytes 0 bytes
explorer-ui-server-cjs (removed) 865.78kB ⬇️
explorer-ui-edge-server-array-push (removed) 83 bytes ⬇️
explorer-ui-client-array-push (removed) 2.31MB ⬇️
synapse-interface-client-array-push (removed) 7.41MB ⬇️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
go Pull requests that update Go code size/s
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants