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

fix(levm): resize memory in generic_call before any validation #1556

Merged
merged 6 commits into from
Dec 23, 2024

Conversation

lima-limon-inc
Copy link
Contributor

@lima-limon-inc lima-limon-inc commented Dec 23, 2024

Motivation

The CALLCODE operand was not resizing the memory with its new size; it was only using the new size to calculate the gas cost. This turned out to be a problem common to all the CALL* family of operands.

Description

Right at the beginning of generic_call, we now resize the memory of the current call frame. This is because, the memory should be expanded even if the caller does not have enough funds to proceed with the transaction.

This comes from the test stRandom/randomStatetest248.json. In this test, the caller is trying to transfer U256::MAX to a different address. In our code, we only expand the memory IF the user has enough funds; but we should expand the memory regardless of funds.

@lima-limon-inc lima-limon-inc self-assigned this Dec 23, 2024
@lima-limon-inc lima-limon-inc added the bug Something isn't working label Dec 23, 2024
@lima-limon-inc lima-limon-inc marked this pull request as ready for review December 23, 2024 12:51
@lima-limon-inc lima-limon-inc requested a review from a team as a code owner December 23, 2024 12:51
@lima-limon-inc lima-limon-inc changed the title fix(levm): Resize memory in CALLCODE operand before generic_call fix(levm): resize memory in CALLCODE operand before generic_call Dec 23, 2024
@maximopalopoli maximopalopoli added the levm Lambda EVM implementation label Dec 23, 2024
Copy link
Contributor

@maximopalopoli maximopalopoli left a comment

Choose a reason for hiding this comment

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

LGTM, now I have a doubt if this should also be done in the other call ops

@JereSalo
Copy link
Contributor

I'm kinda confused about this. It may be accurate behavior but we already do a resizing when we call load_range in generic_call. Are we doing something wrong? Can you elaborate more on the explanation in this? Thanks!
Do we need to do this in other call opcodes?

@lima-limon-inc
Copy link
Contributor Author

LGTM, now I have a doubt if this should also be done in the other call ops

I was thinking the same thing! Let me elaborate

@lima-limon-inc
Copy link
Contributor Author

This comes from the test stRandom/randomStatetest248.json. In this test, the caller is trying to transfer U256::MAX to a different address. In our code, we only expand the memory IF the user has enough funds; but we should expand the memory regardless of funds (or so it seems).

Seen here:
https://github.com/lambdaclass/ethrex/blob/main/crates/vm/levm/src/opcode_handlers/system.rs#L646-L651

We check to see if the user has enough funds, and if not we return. Therefore, load_range is never executed.

Plus, I think this raises some question regarding load_range and calculate_memory_size. They seem to be trying to do similar things, but differently.

Something seems fishy about it.

@lima-limon-inc
Copy link
Contributor Author

I'm kinda confused about this. It may be accurate behavior but we already do a resizing when we call load_range in generic_call. Are we doing something wrong? Can you elaborate more on the explanation in this? Thanks! Do we need to do this in other call opcodes?

Maybe a slight refactor of generic_call instead? Especially if all the call* opcodes have this same behavior

@JereSalo
Copy link
Contributor

So if the appropriate behavior would be to expand memory before making the necessary validations what would happen if the only change that we made to the code would be to just move the load_range to the beginning of generic_call?
Did you find anything in the execution specs regarding this?
I think that by just changing the order in generic_call it should work properly, right? We have expand memory before the validations that push zero to the stack. It sounds quite reasonable.
Let me know the results if you try it.

@lima-limon-inc
Copy link
Contributor Author

So if the appropriate behavior would be to expand memory before making the necessary validations what would happen if the only change that we made to the code would be to just move the load_range to the beginning of generic_call? Did you find anything in the execution specs regarding this? I think that by just changing the order in generic_call it should work properly, right? We have expand memory before the validations that push zero to the stack. It sounds quite reasonable. Let me know the results if you try it.

That was the "refactor" I had in mind! (You know what they say about great minds ;) )
I'm gonna try it and see what happens.

@lima-limon-inc lima-limon-inc marked this pull request as draft December 23, 2024 15:07
@lima-limon-inc lima-limon-inc changed the title fix(levm): resize memory in CALLCODE operand before generic_call fix(levm): resize memory in generic_call before any validation Dec 23, 2024
@lima-limon-inc lima-limon-inc marked this pull request as ready for review December 23, 2024 15:22
@lima-limon-inc
Copy link
Contributor Author

So if the appropriate behavior would be to expand memory before making the necessary validations what would happen if the only change that we made to the code would be to just move the load_range to the beginning of generic_call? Did you find anything in the execution specs regarding this? I think that by just changing the order in generic_call it should work properly, right? We have expand memory before the validations that push zero to the stack. It sounds quite reasonable. Let me know the results if you try it.

Hi Jere, quick update. I pushed (ce3bf5a) said slight refactor.
The same tests pass.

At least according to the python implementation, all CALL* type operands expand the memory; so it would appear to be a "valid change" to do it in generic_call.

They do so before calling generic_call.; however, since we are doing said expansion right at the beginning of generic_call the results are "equivalent". (Similar to what we did with the PC)

@JereSalo JereSalo added this pull request to the merge queue Dec 23, 2024
Merged via the queue into main with commit 409d22a Dec 23, 2024
6 checks passed
@JereSalo JereSalo deleted the fix/levm/callcode branch December 23, 2024 15:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working levm Lambda EVM implementation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants