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

Add nonce validation after broadcast for Hedera #13957

Merged

Conversation

amit-momin
Copy link
Contributor

@amit-momin amit-momin commented Jul 29, 2024

BCI-3843

  • Added a validation to confirm the on-chain nonce incremented immediately after a transaction was broadcasted for Hedera. This check is only applicable to Hedera because it has instant finality and a scenario where a transaction can be included on chain with a receipt but fail to increment the nonce.
  • Added a new RevertReason field was added to the Receipt struct to track this additional message provided by Hedera.

@amit-momin amit-momin marked this pull request as ready for review July 30, 2024 00:17
@amit-momin amit-momin requested review from a team as code owners July 30, 2024 00:17
return errType, err
}
// Check that the transaction count has incremented on-chain to include the broadcasted transaction
// Insufficient transaction fee is a common scenario in which the sequence is not incremented by the chain
Copy link
Collaborator

Choose a reason for hiding this comment

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

Let's be even more explicit about this

Suggested change
// Insufficient transaction fee is a common scenario in which the sequence is not incremented by the chain
// Insufficient transaction fee is a common scenario in which the sequence is not incremented by the chain even though we got a successful response

// Check that the transaction count has incremented on-chain to include the broadcasted transaction
// Insufficient transaction fee is a common scenario in which the sequence is not incremented by the chain
// If the sequence failed to increment and hasn't reached the max retries, return the Underpriced error to try again with a bumped attempt
if nextSeqOnChain.Int64() == txSeq.Int64() && retryCount < maxHederaBroadcastRetries {
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: in theory if nextSeqOnChain is < txSeq we can mark tx as Successful

Copy link
Contributor Author

Choose a reason for hiding this comment

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

nextSeqOnChain < txSeq I think would be an indicator of a nonce gap which wouldn't return a successful errType so we would have exited early. But for a belts and braces approach, I added the condition just in case and mark the tx as Fatal in this case.

Copy link
Contributor

@huangzhen1997 huangzhen1997 Jul 30, 2024

Choose a reason for hiding this comment

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

Maybe @dhaidashenko you meant nextSeqOnChain > txSeq?

I agree that nextSeqOnChain < txSeq would be incorrect and caught by SendTransactionReturnCode early, and probably due to a reorg in this case ? otherwise not sure about how this is possible.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah if that's the case then classifying that as Successful is ok because we process TransactionAlreadyKnown as the same.
Also unsure if nextSeqOnChain < txSeq is a scenario we could realistically hit for this chain. I believe re-orgs aren't possible because of instant finality. But there could be some obscure scenario so this check should help.

Copy link
Collaborator

@dimriou dimriou Jul 31, 2024

Choose a reason for hiding this comment

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

Retryable is also another option for the nextSeqOnChain < txSeq case. There are two scenarios:

  • We have a nonce gap: fatal will alert us sooner, but we might miss reorg cases and it won't recover anyway
  • There was a reorg or RPC was lagging: retryable will handle this, although I found out that Hedera doesn't handle nonce too high errors gracefully, so it will throw a bunch of errors during this process.

dhaidashenko
dhaidashenko previously approved these changes Jul 30, 2024
Copy link
Contributor

@huangzhen1997 huangzhen1997 left a comment

Choose a reason for hiding this comment

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

lgtm except one small nit, but due to the limited knowledge/context I have now, I will just comment instead of approve :)

@@ -600,6 +615,44 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) hand
}
}

func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) validateOnChainSequence(ctx context.Context, lgr logger.SugaredLogger, errType client.SendTxReturnCode, err error, etx txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], retryCount int) (client.SendTxReturnCode, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

shall we rename this function to imply it's only meant for Hedara, or it's better to be generic ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think it's alright either way. I considered that actually but opted to leave it implicit. I'm not against changing it though if others agree

// Check that the transaction count has incremented on-chain to include the broadcasted transaction
// Insufficient transaction fee is a common scenario in which the sequence is not incremented by the chain
// If the sequence failed to increment and hasn't reached the max retries, return the Underpriced error to try again with a bumped attempt
if nextSeqOnChain.Int64() == txSeq.Int64() && retryCount < maxHederaBroadcastRetries {
Copy link
Contributor

@huangzhen1997 huangzhen1997 Jul 30, 2024

Choose a reason for hiding this comment

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

Maybe @dhaidashenko you meant nextSeqOnChain > txSeq?

I agree that nextSeqOnChain < txSeq would be incorrect and caught by SendTransactionReturnCode early, and probably due to a reorg in this case ? otherwise not sure about how this is possible.

dimriou
dimriou previously approved these changes Jul 31, 2024
@dimriou dimriou added this pull request to the merge queue Aug 1, 2024
Merged via the queue into develop with commit 20dbba8 Aug 1, 2024
121 checks passed
@dimriou dimriou deleted the BCI-3843-Use-on-chain-nonce-to-identify-failed-transactions branch August 1, 2024 14:01
l.Warnw("transaction reverted on-chain unable to extract revert reason", "hash", receipt.GetTxHash(), "err", err)
rpcError, errExtract := ec.client.CallContract(ctx, attempt, receipt.GetBlockNumber())
if errExtract == nil {
l.Warnw("transaction reverted on-chain", "hash", receipt.GetTxHash(), "rpcError", rpcError.String())
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: It might make sense to set this reason back on the receipt struct right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think it makes sense to leave this as a log instead of adding it to the Receipt struct. Since the TXM is indifferent to a tx reverting, I don't think we should try to store this to avoid adding another column.

friedemannf added a commit to smartcontractkit/ccip that referenced this pull request Aug 20, 2024
asoliman92 pushed a commit that referenced this pull request Aug 28, 2024
* Added post-broadcast nonce validation for Hedera

* Added changeset

* Updated chaintype docs for Hedera

* Fixed lint errors

* Added condition to handle on-chain seq less than tx seq and updated comment
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.

5 participants