-
Notifications
You must be signed in to change notification settings - Fork 5.9k
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
EOF: Implement ext*calls
#15559
EOF: Implement ext*calls
#15559
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
4e8c5c1
to
626388d
Compare
626388d
to
8ecb35d
Compare
b1cc886
to
fbc76c7
Compare
aa4501a
to
ea37148
Compare
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
ea37148
to
216792c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are a few things that need correcting: memory side-effects, non-existent ext
members on address
, probably unnecessary check for new opcodes outside of EOF. We also have no analysis checks against passing gas
into an external call.
Also, tests are failing.
libyul/AsmAnalysis.cpp
Outdated
"The \"{instruction}\" instruction is {kind} VMs.", | ||
fmt::arg("instruction", boost::to_lower_copy(instructionInfo(_instr, m_evmVersion).name)), | ||
fmt::arg("kind", "not available in legacy bytecode") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any good reason to have an explicit check for specifically these three instructions? We did not do that for the ones we added earlier. Instead we just excluded them from dialect, so that they don't have corresponding builtins and their names still remain usable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because these three opcodes are available in yul (EOF) as regular instructions. Other instructions I added are buildin functions or are unavailable in yul. If we don't add the sanity check fails
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean all added opcodes were till now buildin or are disabled in dialect.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, right. I'm still confusing this bit with the code responsible for making sure instructions are available or not on EOF/legacy. But this only kicks in when we would get an error anyway and just replaces the generic "function not found" with a more specific message explaining why it was not available.
So this is correct, it's the other way around - the dialect builtins should report these specialized messages too if we wanted to be fully consistent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But while thinking about it I realized we're missing a check elsewhere and a very important one - we're missing the special-casing for the EXT*CALL
instructions on legacy. They should be marked as non-reserved in EVMDialect::createReservedIdentifiers()
. Without it, this is breaking for legacy Yul.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And it's actually not just this PR, we're missing such exceptions for nearly all the instructions we added so far. We did that only for auxdataloadn
, but then we forgot dataloadn
, which gets added automatically as all Instruction
s are.
This thing is just too error-prone and we keep realizing we're missing something there (#15550 (comment)). I think that instead of testing it ad-hoc for every new opcode/builtin, we should create a few comprehensive test cases that cover all of them and just keep them updated with new PRs.
We basically need 4 tests. Each one should cover all EOF-only opcodes and all EOF-only builtins and check that:
- The name is not reserved on legacy (can declare variables and functions with that name). Covers
createReservedIdentifiers()
. - The name is reserved on EOF.
- The name is not defined on legacy (calling that name will not execute a Yul builtin). Covers
createBuiltins()
.- If it works on EOF, we get a specialized error saying it's only available on EOF (rather than a generic error about calling undefined function). Covers
validateInstructions()
we have here.
- If it works on EOF, we get a specialized error saying it's only available on EOF (rather than a generic error about calling undefined function). Covers
- It either works on EOF or is not defined (depending on the case).
This can of course be done in a separate PR not to hold this one up. In this one just make sure that these things work correctly for EXT*CALL
instructions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed. I created these tests covering ext*call
in this PR. They should be extended to all added EOF instructions
I think it would be good to enable a few related semantic tests already in this PR. Some external calls and the low-level calls on |
Also, a question about the EOF spec. It says:
Does it simply mean that the opcodes are treated as |
Test are failing because they depend on other PR with stack height calculation. I can regenerate them but I would rather wait until it's merged. |
I have already a version with all semantic tests passing. It required three small fixes but in this case I would not bother now. Moreover we need to introduce Osaka to Solidity to run semantic tests with the newest evmone now. |
It's the same as with all other newly introduced opcodes. Original plan was to enable them also for legacy, then it changed, and this explicit note added to point out the change. |
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
63c2be6
to
45df930
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main remaining thing is #15559 (comment), which I missed previously. I.e. extcall
opcodes must not be reserved identifiers on legacy + a test confirming it works correctly by defining a function/variable with that name.
The same thing needs to be fixed for other opcodes, but that should be done separately, since that's already broken on develop
.
I have already a version with all semantic tests passing. It required three small fixes but in this case I would not bother now. Moreover we need to introduce Osaka to Solidity to run semantic tests with the newest evmone now.
Well, if you prefer we can merge without it, but I'd still recommend enabling at least one just to confirm that late changes in the PR did not break anything.
fe57558
to
7cc0877
Compare
I enabled one but to be able to run any semantic test we need to first merge this #15626 or #15606 |
5d5931c
to
82c21ea
Compare
82c21ea
to
6263f56
Compare
Depends on #15620Merged.Depends on #15626Merged.