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: implement full EOF suite #26133

Closed
wants to merge 53 commits into from
Closed

Conversation

lightclient
Copy link
Member

@lightclient lightclient commented Nov 7, 2022

(wip)

This PR builds on the Ipsilon team's (@gumb0, @chfast, and @axic) earlier work implementing EIP-3540 and EIP-3670. I'm extending it to support the "full" EOF suite which is:

@chfast
Copy link
Member

chfast commented Nov 8, 2022

@hugo-dc is working on EIP-4200 (static relative jumps) implementation: https://github.com/ipsilon/go-ethereum/tree/eip-4200.

core/vm/eof.go Outdated Show resolved Hide resolved
core/vm/eof.go Outdated Show resolved Hide resolved
core/vm/eof.go Outdated Show resolved Hide resolved
core/vm/eof.go Outdated Show resolved Hide resolved
core/vm/eof.go Outdated Show resolved Hide resolved
@holiman
Copy link
Contributor

holiman commented Nov 15, 2022

I wanted to do some cross-client fuzzing, using https://github.com/holiman/txparse/#eof-parser-eofparse as a fuzzing target. However, in order to invoke the parsing from an external package, the external caller needs an instruction set. But none of our instruction sets are public.
I suggest somehow either

a) making the instructionsets public, or
b) making the instructionset constructors public, or
c) making a public eof parser method which internally is able to lookup/create an instruction set for given parameters, or
d) making a constructor for the 'LatestTesting' instruction set.

Locally, I went with option d.

diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go
index 120fb56ae2..1aa3fc4703 100644
--- a/core/vm/jump_table.go
+++ b/core/vm/jump_table.go
@@ -63,6 +63,12 @@ var (
 	shanghaiInstructionSet         = newShanghaiInstructionSet()
 )
 
+// NewLatestInstructionSetForTesting returns the 'latest' instruction set, for use in testing.
+// This method will change over time, and cannot be relied upon to stay consistent across releases.
+func NewLatestInstructionSetForTesting() JumpTable {
+	return newShanghaiInstructionSet()
+}
+
 // JumpTable contains the EVM opcodes supported at a given fork.
 type JumpTable [256]*operation
 

core/vm/eof.go Outdated Show resolved Hide resolved
@holiman
Copy link
Contributor

holiman commented Nov 15, 2022

Now that the masterbranch is go1.19 and up, we could also import this test into this PR: https://github.com/holiman/txparse/blob/main/eofparse/eofparse_test.go

core/vm/interpreter.go Outdated Show resolved Hide resolved
Comment on lines +294 to +357
*pc = 0
*pc -= 1 // hacks xD
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the goal of this hack? Why do you need to set the pc like this?

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, so you want it to be 0 after the loop does +1 later on

core/vm/analysis.go Outdated Show resolved Hide resolved
core/vm/eips.go Outdated Show resolved Hide resolved
core/vm/eips.go Outdated Show resolved Hide resolved
core/vm/eof.go Outdated Show resolved Hide resolved
)

var (
ErrUndefinedInstruction = errors.New("undefined instrustion")
Copy link
Member

Choose a reason for hiding this comment

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

typo: instrustion

var (
code = scope.Contract.CodeAt(scope.CodeSection)
idx = binary.BigEndian.Uint16(code[*pc+1:])
typ = scope.Contract.Container.Types[scope.CodeSection]
Copy link
Member

Choose a reason for hiding this comment

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

It is getting the type of the current CodeSection, not the Code section to be called (idx).

Suggested change
typ = scope.Contract.Container.Types[scope.CodeSection]
typ = scope.Contract.Container.Types[idx]

@@ -262,6 +262,25 @@ func Transition(ctx *cli.Context) error {
return NewError(ErrorConfig, errors.New("EIP-1559 config but missing 'currentBaseFee' in env section"))
}
}
// Sanity check pre-allocated EOF code to not panic in state transition.
if chainConfig.IsShanghai(big.NewInt(int64(prestate.Env.Number))) {
Copy link
Member

Choose a reason for hiding this comment

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

I think t8n tool should also check that before the EOF fork, code in prestate doesn't start with EF00

if want, have := int(metadata[arg].Input), height; want > have {
return 0, fmt.Errorf("%w: at pos %d", ErrStackUnderflow{stackLen: have, required: want}, pos)
}
if have, limit := int(metadata[arg].Output)+height, int(params.StackLimit); have > limit {
Copy link
Member

Choose a reason for hiding this comment

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

I think this should check

Suggested change
if have, limit := int(metadata[arg].Output)+height, int(params.StackLimit); have > limit {
if have, limit := int(metadata[arg].MaxStackHeight)+height, int(params.StackLimit); have > limit {

@lightclient
Copy link
Member Author

This PR is really stale at this point, I think when we need to implement EOF we can use this for inspiration, but will need to do some significant refactoring.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.