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 Transaction Simulation to the TXM #12503

Merged
merged 27 commits into from
Mar 27, 2024
Merged

Conversation

amit-momin
Copy link
Contributor

@amit-momin amit-momin commented Mar 20, 2024

  • Add tx simulation to the TXM to allow product teams to test when a tx on ZK chains will fail due to out of counter (overflow) errors. Does not return any other types of errors. Non-zk chains should never error on this method.
  • Enable tx simulation to easily adapt to chain specific methods
  • Create a default case for all other chains

Copy link
Contributor

I see you updated files related to core. Please run pnpm changeset in the root directory to add a changeset.

Copy link
Contributor

@prashantkumar1982 prashantkumar1982 left a comment

Choose a reason for hiding this comment

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

Could you also update the txManager interface here if @FelixFan1992 agrees with this route?
https://github.com/smartcontractkit/chainlink/blob/develop/core/services/ocrcommon/transmitter.go#L18-L20

@@ -19,6 +19,7 @@ const (
ChainScroll ChainType = "scroll"
ChainWeMix ChainType = "wemix"
ChainXDai ChainType = "xdai" // Deprecated: use ChainGnosis instead
ChainZkEvm ChainType = "zkevm"
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this needed?
Didn't see any behavior depending on this type.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh good call, missed cleaning this out after removing the zkevm specific method

@@ -269,3 +270,12 @@ func (c *chainClient) TransactionReceipt(ctx context.Context, txHash common.Hash
func (c *chainClient) LatestFinalizedBlock(ctx context.Context) (*evmtypes.Head, error) {
return c.multiNode.LatestFinalizedBlock(ctx)
}

func (c *chainClient) CheckTxValidity(ctx context.Context, from common.Address, to common.Address, data []byte) error {
Copy link
Contributor

Choose a reason for hiding this comment

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

How should the product understand if the received error is OOC type?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since we standardize the error we send back, they could use ErrOutOfCounters to determine if the error is an OOC error. I think to make it simpler for them though we'd maybe need to return a second output either another error or a flag. But I took this approach in efforts to keep the return a single field.

Copy link
Contributor

@prashantkumar1982 prashantkumar1982 left a comment

Choose a reason for hiding this comment

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

Looks good for now to unblock ZK chains.

For future, I think we need to come up with a proper error handling strategy for the Chain Client. All RPC calls in the Chain Client should support a standard error parsing logic, and categorization.

@@ -269,3 +270,12 @@ func (c *chainClient) TransactionReceipt(ctx context.Context, txHash common.Hash
func (c *chainClient) LatestFinalizedBlock(ctx context.Context) (*evmtypes.Head, error) {
return c.multiNode.LatestFinalizedBlock(ctx)
}

func (c *chainClient) CheckTxValidity(ctx context.Context, from common.Address, to common.Address, data []byte) *SendError {
Copy link
Collaborator

@dimriou dimriou Mar 26, 2024

Choose a reason for hiding this comment

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

nit: would it make sense to rename this function to something like CheckTxOverflow or something like that to highlight the Zk scope? CheckTxValidity seems a bit vague.

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 agree with this change

Copy link
Collaborator

Choose a reason for hiding this comment

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

Why create a separate simulatorClient instead of adding the logic directly to the existing client?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Before when we were using the custom zkEvm method, it was so we could maintain chain specific code without crowding the client. It's possible now that it's simplified but I think there's a realistic possibility that we may need to support a custom method for a chain that's still in-progress.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I might regret this in the future, but I still prefer to have this inside CheckTxOverflow method. Right now CheckTxOverflow is like a passthrough and has no logic. Chain client is supposed to serve exactly this purpose, which is to implement chain-specific logic that can't go inside multinode. As a reader, it would be easier for me to just read the entire thing under one file instead of having to understand why tx_simulator was created. I don't have a hard stance on this, so if you guys think it's cleaner as it is, then I'm ok keeping it this way.

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 would maybe argue that chain client is more so EVM specific code. So if something requires chain specific code where different EVM chains have different implementation, my opinion is we'd want to separate that from the chain client. That being said, we skipped on using the zkevm chain specific code here so I'm not against moving this to the chain client. We could always separate this out again later when there's a need. But before I do, let me get agreement from others.

Copy link
Contributor

@prashantkumar1982 prashantkumar1982 Mar 26, 2024

Choose a reason for hiding this comment

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

I would be ok with anything here.
Either make some changes here, or wait for the final solution to be clearer wrt other ZK chains, and then make the appropriate code changes.

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'd prefer to wait to avoid another back and forth while product teams are waiting. But I agree we'll have more changes come to this code in the near future when we can make this decision.

@@ -269,3 +270,12 @@ func (c *chainClient) TransactionReceipt(ctx context.Context, txHash common.Hash
func (c *chainClient) LatestFinalizedBlock(ctx context.Context) (*evmtypes.Head, error) {
return c.multiNode.LatestFinalizedBlock(ctx)
}

func (c *chainClient) CheckTxValidity(ctx context.Context, from common.Address, to common.Address, data []byte) *SendError {
Copy link
Collaborator

Choose a reason for hiding this comment

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

How is CheckTxValidity going to be used by products? Do they need a SendError code or a bool response would be sufficient enough. The reason I'm asking is because with this implementation the caller is forced to know about the SendError type, whereas it might be better if it gets abstracted completely.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Prashant and I talked this over a bit in the thread. I don't think this could be handled with just a bool or a basic error type. There might be some additional errors that the product teams could check for when simulating like service unavailable or timeout. If it was a simple bool or error type, they wouldn't be able to differentiate between these which is why we opted to return SendError. That way they could check the specific types of errors with the built in methods like IsOutOfCounters()

Copy link
Contributor

Choose a reason for hiding this comment

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

There's an opportunity to clean up our error responses handling across ALL of chain client interface.
Can't be tackled in this PR, but likely a bigger effort into how to handle errors in standard way, for all of the Chain Client interfaces. Maybe a new ticket.
Created one here: https://smartcontract-it.atlassian.net/browse/BCI-2863

@prashantkumar1982 prashantkumar1982 added this pull request to the merge queue Mar 27, 2024
Merged via the queue into develop with commit dc224a2 Mar 27, 2024
103 checks passed
@prashantkumar1982 prashantkumar1982 deleted the zk-tx-simulation branch March 27, 2024 16:12
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