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

Waiting for receipt in simulation tests. #1571

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

Conversation

StefanIliev545
Copy link
Contributor

Why this change is needed

Please provide a description and a link to the underlying ticket

What changes were made as part of this PR

Please provide a high level list of the changes made

PR checks pre-merging

Please indicate below by ticking the checkbox that you have read and performed the required
PR checks

  • PR checks reviewed and performed

Copy link
Collaborator

@tudor-malene tudor-malene left a comment

Choose a reason for hiding this comment

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

small comment

}

if receipt.Status == types.ReceiptStatusFailed {
return fmt.Errorf("receipt had status failed for transaction %s", txHash.Hex())
Copy link
Collaborator

Choose a reason for hiding this comment

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

why is this an error?

}

time.Sleep(3 * time.Second)
// time.Sleep(3 * time.Second)
Copy link
Collaborator

Choose a reason for hiding this comment

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

remove comment

@@ -36,6 +38,28 @@ func RndBtwTime(min time.Duration, max time.Duration) time.Duration {
return time.Duration(RndBtw(uint64(min.Nanoseconds()), uint64(max.Nanoseconds()))) * time.Nanosecond
}

func AwaitReceiptEth(client ethadapter.EthClient, txHash gethcommon.Hash, timeout time.Duration) error {
Copy link
Contributor

@otherview otherview Nov 2, 2023

Choose a reason for hiding this comment

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

There's an existingAwaitReceiptEth method that we can potentially use instead.

@tudor-malene
Copy link
Collaborator

@StefanIliev545 , what's the status of this PR?

@StefanIliev545
Copy link
Contributor Author

@StefanIliev545 , what's the status of this PR?

I haven't looked at it, but I think @otherview played with the sleep this PR is removing so maybe we can close it? Or am I remembering something else?

@otherview
Copy link
Contributor

@StefanIliev545 , what's the status of this PR?

I haven't looked at it, but I think @otherview played with the sleep this PR is removing so maybe we can close it? Or am I remembering something else?

Yeah I did played around with it but didn't reach a conclusion, ended up not changing anything.. !

@tudor-malene
Copy link
Collaborator

@StefanIliev545 , close or merge?

Copy link

coderabbitai bot commented Dec 19, 2023

Walkthrough

The recent update involves modifying the way Ethereum transactions are handled and awaited upon. A new, possibly more efficient or secure client (AuthObsClient) is now used to await transaction receipts, and this process requires a context for better control over the operation's timeout and cancellation. Additionally, there is a shift towards collecting transactions in a slice for batch processing or analysis, suggesting a move towards a more organized or stateful handling of transactions in simulations.

Changes

File Path Change Summary
integration/common/utils.go - Commented out the AwaitReceiptEth function.
- Changed AwaitReceipt function to use context.Context and *obsclient.AuthObsClient.
integration/simulation/... - Added a transactions slice to store transaction references.
- Modified transaction handling to store results in tx and append to transactions.
- Altered the receipt awaiting mechanism to use a new context and timeout.

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 X ?


Tips

Chat with CodeRabbit Bot (@coderabbitai)

  • You can reply to a review comment made by CodeRabbit.
  • You can tag CodeRabbit on specific lines of code or files in the PR by tagging @coderabbitai in a comment.
  • You can tag @coderabbitai in a PR comment and ask one-off questions about the PR and the codebase. Use quoted replies to pass the context for follow-up questions.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • The JSON schema for the configuration file is available here.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/coderabbit-overrides.v2.json

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.

Review Status

Actionable comments generated: 7

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 98e0913 and 1d410b8.
Files selected for processing (2)
  • integration/common/utils.go (1 hunks)
  • integration/simulation/simulation.go (1 hunks)
Additional comments: 20
integration/common/utils.go (15)
  • 67-67: The AwaitReceipt function has been correctly updated to use the context.Context and *obsclient.AuthObsClient. This aligns with the PR objectives to improve the handling of transaction receipts in simulation tests.

  • 67-67: The AwaitReceipt function's error handling for rpc.ErrNilResponse seems to be missing in the new implementation. If this is intentional due to changes in the client.TransactionReceipt method's behavior, it's fine. Otherwise, this might be an oversight that could lead to unhandled errors.

+ if err != nil && !errors.Is(err, rpc.ErrNilResponse) && !errors.Is(err, errutil.ErrNotFound) {
+     // we only retry for a nil "not found" response. This is a different error, so we bail out of the retry loop
+     return retry.FailFast(err)
+ }
  • 59-59: The error message for a failed transaction receipt status is clear and informative. However, ensure that this error handling is consistent with the rest of the codebase and that the failed status is handled as expected in all calling functions.

  • 65-65: The AwaitReceiptEth function is still present and has been updated to use context.Context. This seems to contradict the AI-generated summary which mentioned the removal of this function. If this function is still required, ensure that all references to the old AwaitReceiptEth are updated to use this new signature.

  • 65-65: The AwaitReceiptEth function now returns a *types.Receipt along with an error. This is a change from the previous version which only returned an error. Ensure that all callers of this function are updated to handle the returned receipt.

  • 65-65: The AwaitReceiptEth function uses retry.Do with a retry.NewTimeoutStrategy. Ensure that the retry strategy is consistent with the desired behavior and that the timeout values are configured appropriately for the expected transaction confirmation times.

  • 65-65: The AwaitReceiptEth function checks for receipt.Status == types.ReceiptStatusFailed and returns an error if the status is failed. This is good practice as it ensures that only successful transactions are considered valid. Ensure that this check is consistent with the rest of the codebase.

  • 65-65: The AwaitReceiptEth function's error message for a failed receipt status includes the transaction hash. This is helpful for debugging and is a good practice.

  • 65-65: The AwaitReceiptEth function's error handling seems to be inconsistent with the AwaitReceipt function. The AwaitReceipt function uses errors.Is(err, rpc.ErrNilResponse), while AwaitReceiptEth uses errors.Is(err, errutil.ErrNotFound). Ensure that the error handling is consistent and correct for the context in which each function is used.

+ if err != nil && !errors.Is(err, rpc.ErrNilResponse) {
+     // we only retry for a nil "not found" response. This is a different error, so we bail out of the retry loop
+     return retry.FailFast(err)
+ }
  • 65-65: The AwaitReceiptEth function's error message for a failed transaction receipt status is clear and informative. However, ensure that this error handling is consistent with the rest of the codebase and that the failed status is handled as expected in all calling functions.

  • 65-65: The AwaitReceiptEth function now returns a *types.Receipt along with an error. This is a change from the previous version which only returned an error. Ensure that all callers of this function are updated to handle the returned receipt.

  • 65-65: The AwaitReceiptEth function uses retry.Do with a retry.NewTimeoutStrategy. Ensure that the retry strategy is consistent with the desired behavior and that the timeout values are configured appropriately for the expected transaction confirmation times.

  • 65-65: The AwaitReceiptEth function checks for receipt.Status == types.ReceiptStatusFailed and returns an error if the status is failed. This is good practice as it ensures that only successful transactions are considered valid. Ensure that this check is consistent with the rest of the codebase.

  • 65-65: The AwaitReceiptEth function's error message for a failed receipt status includes the transaction hash. This is helpful for debugging and is a good practice.

  • 65-65: The AwaitReceiptEth function's error handling seems to be inconsistent with the AwaitReceipt function. The AwaitReceipt function uses errors.Is(err, rpc.ErrNilResponse), while AwaitReceiptEth uses errors.Is(err, errutil.ErrNotFound). Ensure that the error handling is consistent and correct for the context in which each function is used.

+ if err != nil && !errors.Is(err, rpc.ErrNilResponse) {
+     // we only retry for a nil "not found" response. This is a different error, so we bail out of the retry loop
+     return retry.FailFast(err)
+ }
integration/simulation/simulation.go (5)
  • 148-175: The changes to bridgeFundingToObscuro function include the introduction of a transactions slice and the use of testcommon.AwaitReceiptEth with a context and timeout. Ensure that the transactions slice is used appropriately throughout the codebase and that the replacement of testcommon.AwaitReceiptEth aligns with the updated AwaitReceipt function in utils.go.

  • 148-175: The bridgeFundingToObscuro function uses a wait group to wait for all transactions to be processed. This is a good practice for concurrent operations. Ensure that the wait group is used correctly and that all goroutines are properly managed.

  • 148-175: The bridgeFundingToObscuro function appends transactions to the transactions slice and then processes them concurrently. Ensure that the slice is not being modified concurrently, which could lead to race conditions.

sync.Mutex // Consider using a mutex to protect the slice during concurrent access
  • 148-175: The bridgeFundingToObscuro function uses a wait group to wait for all transactions to be processed. This is a good practice for concurrent operations. Ensure that the wait group is used correctly and that all goroutines are properly managed.

  • 148-175: The bridgeFundingToObscuro function appends transactions to the transactions slice and then processes them concurrently. Ensure that the slice is not being modified concurrently, which could lead to race conditions.

sync.Mutex // Consider using a mutex to protect the slice during concurrent access

Comment on lines 42 to 63
/*
func AwaitReceiptEth(client ethadapter.EthClient, txHash gethcommon.Hash, timeout time.Duration) error {
var receipt *types.Receipt
var err error
err = retry.Do(func() error {
receipt, err = client.TransactionReceipt(txHash)
if err != nil && !errors.Is(err, rpc.ErrNilResponse) && !errors.Is(err, ethereum.NotFound) {
// we only retry for a nil "not found" response. This is a different error, so we bail out of the retry loop
return retry.FailFast(err)
}
return err
}, retry.NewTimeoutStrategy(timeout, _awaitReceiptPollingInterval))
if err != nil {
return fmt.Errorf("could not retrieve receipt for transaction %s - %w", txHash.Hex(), err)
}

if receipt.Status == types.ReceiptStatusFailed {
return fmt.Errorf("receipt had status failed for transaction %s", txHash.Hex())
}

return nil
}*/
Copy link

Choose a reason for hiding this comment

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

The AwaitReceiptEth function is commented out. If this function is not intended for use and is being replaced by AwaitReceipt, it should be removed to avoid confusion and maintain code cleanliness.

- /*
- func AwaitReceiptEth(client ethadapter.EthClient, txHash gethcommon.Hash, timeout time.Duration) error {
- ...
- }*/

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.

Suggested change
/*
func AwaitReceiptEth(client ethadapter.EthClient, txHash gethcommon.Hash, timeout time.Duration) error {
var receipt *types.Receipt
var err error
err = retry.Do(func() error {
receipt, err = client.TransactionReceipt(txHash)
if err != nil && !errors.Is(err, rpc.ErrNilResponse) && !errors.Is(err, ethereum.NotFound) {
// we only retry for a nil "not found" response. This is a different error, so we bail out of the retry loop
return retry.FailFast(err)
}
return err
}, retry.NewTimeoutStrategy(timeout, _awaitReceiptPollingInterval))
if err != nil {
return fmt.Errorf("could not retrieve receipt for transaction %s - %w", txHash.Hex(), err)
}
if receipt.Status == types.ReceiptStatusFailed {
return fmt.Errorf("receipt had status failed for transaction %s", txHash.Hex())
}
return nil
}*/


return nil
}*/

// AwaitReceipt blocks until the receipt for the transaction with the given hash has been received. Errors if the
Copy link

Choose a reason for hiding this comment

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

The AwaitReceiptEth function prints to the console with fmt.Println. This is not a standard approach for logging in production code and could be replaced with a structured logging framework that allows for log levels and better control over log output.

- fmt.Println("Fetching receipt for tx: ", txHash.Hex())
- fmt.Println("No tx receipt after: ", time.Since(startTime))
+ // Use structured logging instead
+ log.Info("Fetching receipt for tx", "txHash", txHash.Hex())
+ log.Info("No tx receipt after", "duration", time.Since(startTime))

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.

Suggested change
// AwaitReceipt blocks until the receipt for the transaction with the given hash has been received. Errors if the
// AwaitReceipt blocks until the receipt for the transaction with the given hash has been received. Errors if the
// Use structured logging instead
log.Info("Fetching receipt for tx", "txHash", txHash.Hex())
log.Info("No tx receipt after", "duration", time.Since(startTime))

The AwaitReceiptEth function's use of fmt.Println for logging is not ideal. Consider using a structured logging approach for better log management and consistency across the codebase.

- fmt.Println("Fetching receipt for tx: ", txHash.Hex())
- fmt.Println("No tx receipt after: ", time.Since(startTime))
+ // Replace with structured logging
+ log.Info("Fetching receipt for tx", "txHash", txHash.Hex())
+ log.Info("No tx receipt after", "duration", time.Since(startTime))

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.

Suggested change
// AwaitReceipt blocks until the receipt for the transaction with the given hash has been received. Errors if the
// AwaitReceipt blocks until the receipt for the transaction with the given hash has been received. Errors if the
// Replace with structured logging
log.Info("Fetching receipt for tx", "txHash", txHash.Hex())
log.Info("No tx receipt after", "duration", time.Since(startTime))

The AwaitReceiptEth function prints to the console with fmt.Println. This is not a standard approach for logging in production code and could be replaced with a structured logging framework that allows for log levels and better control over log output.

- fmt.Println("Fetching receipt for tx: ", txHash.Hex())
- fmt.Println("No tx receipt after: ", time.Since(startTime))
+ // Use structured logging instead
+ log.Info("Fetching receipt for tx", "txHash", txHash.Hex())
+ log.Info("No tx receipt after", "duration", time.Since(startTime))

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.

Suggested change
// AwaitReceipt blocks until the receipt for the transaction with the given hash has been received. Errors if the
// AwaitReceipt blocks until the receipt for the transaction with the given hash has been received. Errors if the
// Use structured logging instead
log.Info("Fetching receipt for tx", "txHash", txHash.Hex())
log.Info("No tx receipt after", "duration", time.Since(startTime))

The AwaitReceiptEth function's use of fmt.Println for logging is not ideal. Consider using a structured logging approach for better log management and consistency across the codebase.

- fmt.Println("Fetching receipt for tx: ", txHash.Hex())
- fmt.Println("No tx receipt after: ", time.Since(startTime))
+ // Replace with structured logging
+ log.Info("Fetching receipt for tx", "txHash", txHash.Hex())
+ log.Info("No tx receipt after", "duration", time.Since(startTime))

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.

Suggested change
// AwaitReceipt blocks until the receipt for the transaction with the given hash has been received. Errors if the
// AwaitReceipt blocks until the receipt for the transaction with the given hash has been received. Errors if the
// Replace with structured logging
log.Info("Fetching receipt for tx", "txHash", txHash.Hex())
log.Info("No tx receipt after", "duration", time.Since(startTime))

Comment on lines +148 to +175
transactions := make(types.Transactions, 0)
for idx, w := range wallets {
opts, err := bind.NewKeyedTransactorWithChainID(w.PrivateKey(), w.ChainID())
if err != nil {
panic(err)
}
opts.Value = value

_, err = busCtr.SendValueToL2(opts, receivers[idx], value)
tx, err := busCtr.SendValueToL2(opts, receivers[idx], value)
if err != nil {
panic(err)
}
transactions = append(transactions, tx)
}

time.Sleep(15 * time.Second)
// todo - fix the wait group, for whatever reason it does not find a receipt...
/*wg := sync.WaitGroup{}
wg := sync.WaitGroup{}
for _, tx := range transactions {
wg.Add(1)
transaction := tx
go func() {
defer wg.Done()
err := testcommon.AwaitReceiptEth(s.ctx, s.RPCHandles.RndEthClient(), transaction.Hash(), 20*time.Second)
_, err := testcommon.AwaitReceiptEth(context.Background(), s.RPCHandles.RndEthClient().EthClient(), transaction.Hash(), 2*time.Minute)
if err != nil {
panic(err)
}
}()
}
wg.Wait()*/
wg.Wait()
Copy link

Choose a reason for hiding this comment

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

The use of panic for error handling in the bridgeFundingToObscuro function is not ideal for production code. Consider using error returns and handling them gracefully to avoid crashing the entire application.

- panic(err)
+ // Handle error without panicking
+ return fmt.Errorf("error while sending value to L2: %w", err)

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.

Suggested change
transactions := make(types.Transactions, 0)
for idx, w := range wallets {
opts, err := bind.NewKeyedTransactorWithChainID(w.PrivateKey(), w.ChainID())
if err != nil {
panic(err)
}
opts.Value = value
_, err = busCtr.SendValueToL2(opts, receivers[idx], value)
tx, err := busCtr.SendValueToL2(opts, receivers[idx], value)
if err != nil {
panic(err)
}
transactions = append(transactions, tx)
}
time.Sleep(15 * time.Second)
// todo - fix the wait group, for whatever reason it does not find a receipt...
/*wg := sync.WaitGroup{}
wg := sync.WaitGroup{}
for _, tx := range transactions {
wg.Add(1)
transaction := tx
go func() {
defer wg.Done()
err := testcommon.AwaitReceiptEth(s.ctx, s.RPCHandles.RndEthClient(), transaction.Hash(), 20*time.Second)
_, err := testcommon.AwaitReceiptEth(context.Background(), s.RPCHandles.RndEthClient().EthClient(), transaction.Hash(), 2*time.Minute)
if err != nil {
panic(err)
}
}()
}
wg.Wait()*/
wg.Wait()
transactions := make(types.Transactions, 0)
for idx, w := range wallets {
opts, err := bind.NewKeyedTransactorWithChainID(w.PrivateKey(), w.ChainID())
if err != nil {
// Handle error without panicking
return fmt.Errorf("error while creating transactor: %w", err)
}
opts.Value = value
tx, err := busCtr.SendValueToL2(opts, receivers[idx], value)
if err != nil {
// Handle error without panicking
return fmt.Errorf("error while sending value to L2: %w", err)
}
transactions = append(transactions, tx)
}
wg := sync.WaitGroup{}
for _, tx := range transactions {
wg.Add(1)
transaction := tx
go func() {
defer wg.Done()
_, err := testcommon.AwaitReceiptEth(context.Background(), s.RPCHandles.RndEthClient().EthClient(), transaction.Hash(), 2*time.Minute)
if err != nil {
// Handle error without panicking
return fmt.Errorf("error while waiting for receipt: %w", err)
}
}()
}
wg.Wait()

The bridgeFundingToObscuro function's use of panic for error handling is not ideal. Consider using error returns and handling them gracefully to avoid crashing the entire application.

- panic(err)
+ // Handle error without panicking
+ return fmt.Errorf("error while sending value to L2: %w", err)

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.

Suggested change
transactions := make(types.Transactions, 0)
for idx, w := range wallets {
opts, err := bind.NewKeyedTransactorWithChainID(w.PrivateKey(), w.ChainID())
if err != nil {
panic(err)
}
opts.Value = value
_, err = busCtr.SendValueToL2(opts, receivers[idx], value)
tx, err := busCtr.SendValueToL2(opts, receivers[idx], value)
if err != nil {
panic(err)
}
transactions = append(transactions, tx)
}
time.Sleep(15 * time.Second)
// todo - fix the wait group, for whatever reason it does not find a receipt...
/*wg := sync.WaitGroup{}
wg := sync.WaitGroup{}
for _, tx := range transactions {
wg.Add(1)
transaction := tx
go func() {
defer wg.Done()
err := testcommon.AwaitReceiptEth(s.ctx, s.RPCHandles.RndEthClient(), transaction.Hash(), 20*time.Second)
_, err := testcommon.AwaitReceiptEth(context.Background(), s.RPCHandles.RndEthClient().EthClient(), transaction.Hash(), 2*time.Minute)
if err != nil {
panic(err)
}
}()
}
wg.Wait()*/
wg.Wait()
transactions := make(types.Transactions, 0)
for idx, w := range wallets {
opts, err := bind.NewKeyedTransactorWithChainID(w.PrivateKey(), w.ChainID())
if err != nil {
// Handle error without panicking
return fmt.Errorf("error while sending value to L2: %w", err)
}
opts.Value = value
tx, err := busCtr.SendValueToL2(opts, receivers[idx], value)
if err != nil {
// Handle error without panicking
return fmt.Errorf("error while sending value to L2: %w", err)
}
transactions = append(transactions, tx)
}
wg := sync.WaitGroup{}
for _, tx := range transactions {
wg.Add(1)
transaction := tx
go func() {
defer wg.Done()
_, err := testcommon.AwaitReceiptEth(context.Background(), s.RPCHandles.RndEthClient().EthClient(), transaction.Hash(), 2*time.Minute)
if err != nil {
// Handle error without panicking
return fmt.Errorf("error while sending value to L2: %w", err)
}
}()
}
wg.Wait()

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.

3 participants