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

core/vm: Make INVALID a defined opcode #24017

Merged
merged 2 commits into from Dec 17, 2021
Merged

Conversation

gumb0
Copy link
Member

@gumb0 gumb0 commented Nov 29, 2021

This doesn't change anything except error message, but will be required for EOF code calidation (EIP-3670) It doesn't solve the needs of EIP-3670 anymore (because undefined and INVALID are not distinguished in jump table), but does improve the traces.

Before:

> build/bin/evm --code "0xfe" --json --debug run
{"pc":0,"op":254,"gas":"0x2540be400","gasCost":"0x0","memory":"0x","memSize":0,"stack":[],"returnData":"0x","depth":1,"refund":0,"opName":"opcode 0xfe not defined","error":"invalid opcode: opcode 0xfe not defined"}
{"output":"","gasUsed":"0x2540be400","time":132537,"error":"invalid opcode: opcode 0xfe not defined"}
#### LOGS ####

After:

> build/bin/evm --code "0xfe" --json --debug run
{"pc":0,"op":254,"gas":"0x2540be400","gasCost":"0x0","memory":"0x","memSize":0,"stack":[],"returnData":"0x","depth":1,"refund":0,"opName":"INVALID","error":""}
{"output":"","gasUsed":"0x2540be400","time":119327,"error":"invalid opcode: INVALID"}
#### LOGS ####

@@ -36,6 +36,7 @@ var (
ErrGasUintOverflow = errors.New("gas uint64 overflow")
ErrInvalidCode = errors.New("invalid code: must not begin with 0xef")
ErrNonceUintOverflow = errors.New("nonce uint64 overflow")
ErrInvalidOpcode = errors.New("exection reached INVALID (0xfe) opcode")
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
ErrInvalidOpcode = errors.New("exection reached INVALID (0xfe) opcode")
ErrInvalidOpcode = errors.New("execution reached INVALID (0xfe) opcode")

Copy link
Member

Choose a reason for hiding this comment

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

Could also just say:

Suggested change
ErrInvalidOpcode = errors.New("exection reached INVALID (0xfe) opcode")
ErrInvalidOpcode = errors.New("aborted with INVALID (0xfe) opcode")

Copy link
Member

Choose a reason for hiding this comment

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

Lastly with EIP-1803 I hope we can rename INVALID to ABORT to make it more clear, but that should be a separate PR I suppose?

@gumb0 gumb0 force-pushed the invalid-opcode branch 3 times, most recently from 2676eda to e2aefed Compare November 29, 2021 18:42
Copy link
Contributor

@holiman holiman left a comment

Choose a reason for hiding this comment

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

Overall, I'm not quite convinced about the need for doing this. Can you elaborate on that?

@@ -36,6 +36,7 @@ var (
ErrGasUintOverflow = errors.New("gas uint64 overflow")
ErrInvalidCode = errors.New("invalid code: must not begin with 0xef")
ErrNonceUintOverflow = errors.New("nonce uint64 overflow")
ErrInvalidOpcode = errors.New("aborted with INVALID (0xfe) opcode")
Copy link
Contributor

Choose a reason for hiding this comment

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

We already have an ErrInvalidOpCode, as a type, defined further down in this file. Having a type with the same name as a global var is not a good idea.

IMO let's not define a new specific error for this specific opcode -- the idea with 0xFE is that it will always remain undefined. There are others currently undefined, and IMO this opcode should be treated exactly like those, by the EVM.

So I think we can skip this var here. And the opInvaid could just do

return nil, &ErrInvalidOpCode{opcode: OpCode(0xfe)}

@gumb0
Copy link
Member Author

gumb0 commented Nov 30, 2021

Overall, I'm not quite convinced about the need for doing this. Can you elaborate on that?

With EOF we propose (in EIP-3670) to forbid deploying undefined opcodes (which will allow introducing new opcodes later without bumping EOF version and also simplifies EVM implementation, where it needs only EOF version (without additional revision) to know if particular byte value is defined)

0xfe should still be allowed to deploy as a guaranteed way to fail execution, so this is where it differs from all other bytes that are not defined.

Also a minor point: having an enum value for INVALID helps to clarify EIP-3540 rules in code, see this discussion #22958 (comment)

@gumb0
Copy link
Member Author

gumb0 commented Nov 30, 2021

0xfe should still be allowed to deploy as a guaranteed way to fail execution, so this is where it differs from all other bytes that are not defined.

And I have EIP-3670 implementation where I use jumpTable[opcode] == nil to find if the opcode is defined, that's what required this PR.

Comment on lines 1008 to 1003
INVALID: {
execute: opInvalid,
constantGas: 0,
minStack: minStack(0, 0),
maxStack: maxStack(0, 0),
},
Copy link
Contributor

Choose a reason for hiding this comment

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

Though -- in the context of what you're implementing in that other PR... Is it really necessary to define it as an acutal op in the jumptable, as opposed to just define the OpCode but leave it empty in the jumptable?

Copy link
Member 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 better to have it in the jumptable, I see the question of whether 0xfe is a defined opcode as a property of particular fork rules (currently it's defined in all forks, but theoretically 0xfe might mean something else in some other jump table)

Without putting it into jumptable I can only think of having it as a special case in code validation, like jumpTable[opcode] == nil && opcode != 0xfe will mean it's not defined.

@axic
Copy link
Member

axic commented Dec 9, 2021

As discussed with @gumb0, opInvalid may be required for the EIP-3670-style code validation, but lets tackle that once @gumb0 opens a draft PR for that. This change (defining the instruction) is useful for logging purposes as well as for consumers of the instruction set for (dis)assembly purposes (such as goevmlab). As a reference, most assemblers (including Solidity) out there support invalid as an opcode.

Copy link
Contributor

@holiman holiman left a comment

Choose a reason for hiding this comment

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

LGTM

@holiman holiman added this to the 1.10.14 milestone Dec 17, 2021
@holiman holiman merged commit 3e47e38 into ethereum:master Dec 17, 2021
@holiman holiman deleted the invalid-opcode branch December 17, 2021 12:44
sidhujag pushed a commit to syscoin/go-ethereum that referenced this pull request Dec 19, 2021
* core/vm: Define 0xfe opcode as INVALID

* core/vm: Remove opInvalid as opUndefined handles it

Co-authored-by: Alex Beregszaszi <alex@rtfs.hu>
JacekGlen pushed a commit to JacekGlen/go-ethereum that referenced this pull request May 26, 2022
* core/vm: Define 0xfe opcode as INVALID

* core/vm: Remove opInvalid as opUndefined handles it

Co-authored-by: Alex Beregszaszi <alex@rtfs.hu>
HAOYUatHZ pushed a commit to scroll-tech/go-ethereum that referenced this pull request Jun 22, 2022
* core/vm: Define 0xfe opcode as INVALID

* core/vm: Remove opInvalid as opUndefined handles it

Co-authored-by: Alex Beregszaszi <alex@rtfs.hu>
HAOYUatHZ added a commit to scroll-tech/go-ethereum that referenced this pull request Jun 22, 2022
core/vm: Make INVALID a defined opcode (ethereum#24017)

* core/vm: Define 0xfe opcode as INVALID

* core/vm: Remove opInvalid as opUndefined handles it

Co-authored-by: Alex Beregszaszi <alex@rtfs.hu>

Co-authored-by: Andrei Maiboroda <andrei@ethereum.org>
Co-authored-by: Alex Beregszaszi <alex@rtfs.hu>
yperbasis added a commit to ledgerwatch/erigon that referenced this pull request Dec 30, 2022
Cherry-pick ethereum/go-ethereum#24017.

* core/vm: Define 0xfe opcode as INVALID

* core/vm: Remove opInvalid as opUndefined handles it

Co-authored-by: Alex Beregszaszi <alex@rtfs.hu>

Co-authored-by: Andrei Maiboroda <andrei@ethereum.org>
Co-authored-by: Alex Beregszaszi <alex@rtfs.hu>
gzliudan added a commit to gzliudan/XDPoSChain that referenced this pull request Feb 23, 2024
gzliudan added a commit to gzliudan/XDPoSChain that referenced this pull request Feb 23, 2024
gzliudan added a commit to gzliudan/XDPoSChain that referenced this pull request Feb 23, 2024
gzliudan added a commit to gzliudan/XDPoSChain that referenced this pull request Feb 26, 2024
gzliudan added a commit to gzliudan/XDPoSChain that referenced this pull request Feb 27, 2024
gzliudan pushed a commit to gzliudan/XDPoSChain that referenced this pull request Feb 27, 2024
* core/vm: Define 0xfe opcode as INVALID

* core/vm: Remove opInvalid as opUndefined handles it

Co-authored-by: Alex Beregszaszi <alex@rtfs.hu>
gzliudan pushed a commit to gzliudan/XDPoSChain that referenced this pull request Feb 27, 2024
* core/vm: Define 0xfe opcode as INVALID

* core/vm: Remove opInvalid as opUndefined handles it

Co-authored-by: Alex Beregszaszi <alex@rtfs.hu>
gzliudan pushed a commit to gzliudan/XDPoSChain that referenced this pull request Mar 1, 2024
* core/vm: Define 0xfe opcode as INVALID

* core/vm: Remove opInvalid as opUndefined handles it

Co-authored-by: Alex Beregszaszi <alex@rtfs.hu>
gzliudan pushed a commit to gzliudan/XDPoSChain that referenced this pull request Mar 1, 2024
* core/vm: Define 0xfe opcode as INVALID

* core/vm: Remove opInvalid as opUndefined handles it

Co-authored-by: Alex Beregszaszi <alex@rtfs.hu>
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.

None yet

3 participants