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

Speed up signature check for orders with no pre-interactions #2953

Merged
merged 4 commits into from
Sep 9, 2024

Conversation

m-lord-renkse
Copy link
Contributor

Description

Speed up signature check for orders with no pre-interactions by directly calling isValidSignature instead of our Signatures contract.

Changes

  • In the cases with no pre-interactions, directly call isValidSignature
  • Modify the eht safe e2e tests to use properly a SAFE transaction using the corresponding signature and forcing the new code to be tested/executed

How to test

  1. Acceptance tests

Performance improvement

By looking at the Signatures contract, it is apparent that the speed it is apparent that the improvement won't be significant. We are mostly passing some small checks from the smart contract to Rust code, but the heavy operations are still done in the smart contract.

I did some speed tests locally (I know the numbers will differ in real production, but I wanted to get some approximation). What I did is to do Instant::now() + now.elapse() wrapping the critical code, and after many tests, and I got in average these results:

  • Previous implementation: 2982196 nanoseconds
  • New implementation: 2388463 nanoseconds

There is definitely an improvement. In production the improvement should be greater, because I was using anvil in localhost which reduces the latency significantly.

# Description
Currently the `autopilot` maintenance loop can get stuck when the
configured cow amm helper contract does not support a found contract
with this error:
```
2024-09-03T06:13:17.420Z  WARN autopilot::maintenance: failed to run background task successfully err=method 'tokens(address):(address[])' failure: contract call reverted with message: None

Caused by:
    contract call reverted with message: None
```

So far we have been retrying this error over and over although the call
to detect which tokens the pool is trading will never work if an amm is
misconfigured or generally not supported by the helper contract.

# Changes
Differentiate between retryable and fatal errors while indexing the amms
and retry or skip this pool respectively.

# Testplan
Set up sepolia configuration locally and checked that we don't get stuck
on the unsupported pools:
```
2024-09-03T06:24:55.880Z  INFO cow_amm::cache: helper contract does not support amm cow_amm=0xe4abfda4e8c02fcafc34981dafaeb426aa4186e6 err=MethodError { signature: "tokens(address):(address[])", inner: Revert(None) }
2024-09-03T06:24:55.921Z  INFO cow_amm::cache: indexed new cow amm cow_amm=0xac140f325afd20a733e12580aeb22ff9bf46982f
2024-09-03T06:24:55.956Z  INFO cow_amm::cache: indexed new cow amm cow_amm=0xa54442606548bf1b627662a465a40b31b7e8e711
```
# Description
Indexing refunds is not strictly necessary to have all relevant state
for building the next auction. That's why it's okay to move that logic
off of the critical path.
This should resolve the start up issues we've been seeing on arbitrum
staging where we have to reindex lots of blocks because the blocktime is
so fast and we don't do refunds regularly. However, we should still find
a better way to store the blocks we already indexed to avoid these
issues in general.

# Changes
Index refund events in a separate background task again.
@m-lord-renkse m-lord-renkse force-pushed the speed-up-sign-check-for-no-pre-interactions branch from 741e43a to c2c5381 Compare September 6, 2024 07:56
@m-lord-renkse m-lord-renkse marked this pull request as ready for review September 6, 2024 08:11
@m-lord-renkse m-lord-renkse requested a review from a team as a code owner September 6, 2024 08:11
@squadgazzz
Copy link
Contributor

squadgazzz commented Sep 6, 2024

Previous implementation: 2982196 nanoseconds
New implementation: 2388463 nanoseconds
There is definitely an improvement. In production the improvement should be greater, because I was using anvil in localhost which reduces the latency significantly.

It would be better to create an image to run it on prod for a while(like it was done with recent improvement PRs). Just be aware to checkout from the latest release tag.

So, currently, I see the improvement will be in the network delay only, right? Oh, wait, we still call the contract. There won't be any improvement at all(a few nanosecs don't count IMO)?

       let magic_bytes = contract
            .methods()
            .is_valid_signature(Bytes(check.hash), Bytes(check.signature.clone()))
            .call()
            .await

@m-lord-renkse
Copy link
Contributor Author

Previous implementation: 2982196 nanoseconds
New implementation: 2388463 nanoseconds
There is definitely an improvement. In production the improvement should be greater, because I was using anvil in localhost which reduces the latency significantly.

It would be better to create an image to run it on prod for a while(like it was done with recent improvement PRs). Just be aware to checkout from the latest release tag.

So, currently, I see the improvement will be in the network delay only, right? Oh, wait, we still call the contract. There won't be any improvement at all(a few nanosecs don't count IMO)?

       let magic_bytes = contract
            .methods()
            .is_valid_signature(Bytes(check.hash), Bytes(check.signature.clone()))
            .call()
            .await

Yeah, we should definitely run it on prod and see the impact, but I am afraid the impact will be so small that it won't be seen in the noise 🤔

The improvement is the contract we call, in the previous code, we always call a contract function which checks the signature taking into account the pre-interactions, so the smart contract checks if the pre-interactions are filled or not, and then call isValidSignature. So now, we call directly isValidSignature if the pre-interactions are empty. We move some checks from smart contract to Rust code.

Performance wise, it will be better for sure. How much? we don't know, but I assume it will reach 1 ms at most. But it is my educated guess.

@MartinquaXD
Copy link
Contributor

I am afraid the impact will be so small that it won't be seen in the noise 🤔

If the impact is not measurable we shouldn't merge the code IMO. All of these optimizations are just things that could improve the runtime but ultimately might not for whatever reason so it's inherently a research task.

Oh, wait, we still call the contract. There won't be any improvement at all(a few nanosecs don't count IMO)?

Mateo's benchmark showed an improvement of 20% on the request itself. If we add network latency to the mix this in itself will likely not be a significant improvement but this could have a compounding impact due to the RPC request batching which works worse if fast and slow requests happen to be in the same batch.

Ultimately we should benchmark in prod and only merge if this improves the runtime.

@m-lord-renkse
Copy link
Contributor Author

Ultimately we should benchmark in prod and only merge if this improves the runtime.

Yes, I agree. I already did the job, so it's worth trying it at least. I will do it on Monday (I don't want to leave it running unsupervised over the weekend) 👌

@MartinquaXD
Copy link
Contributor

Yes, I agree. I already did the job, so it's worth trying it at least. I will do it on Monday (I don't want to leave it running unsupervised over the weekend) 👌

I don't want our speed initiatives to drag on too much. I can test it out over the weekend since I'll probably be working some more as oncall anyway.

@m-lord-renkse
Copy link
Contributor Author

Yes, I agree. I already did the job, so it's worth trying it at least. I will do it on Monday (I don't want to leave it running unsupervised over the weekend) 👌

I don't want our speed initiatives to drag on too much. I can test it out over the weekend since I'll probably be working some more as oncall anyway.

@MartinquaXD That would be lovely 🙏 thank you very much!

Copy link
Contributor

@squadgazzz squadgazzz left a comment

Choose a reason for hiding this comment

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

Lg

@m-lord-renkse m-lord-renkse force-pushed the speed-up-sign-check-for-no-pre-interactions branch 5 times, most recently from 5b77210 to fda6060 Compare September 9, 2024 12:43
@m-lord-renkse m-lord-renkse force-pushed the speed-up-sign-check-for-no-pre-interactions branch from fda6060 to c0a77f0 Compare September 9, 2024 12:45
@m-lord-renkse m-lord-renkse merged commit a25053d into main Sep 9, 2024
12 checks passed
@m-lord-renkse m-lord-renkse deleted the speed-up-sign-check-for-no-pre-interactions branch September 9, 2024 15:02
@github-actions github-actions bot locked and limited conversation to collaborators Sep 9, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants