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

cannon: 64-bit Refactor #12029

Merged
merged 11 commits into from
Oct 1, 2024
Merged

cannon: 64-bit Refactor #12029

merged 11 commits into from
Oct 1, 2024

Conversation

Inphi
Copy link
Contributor

@Inphi Inphi commented Sep 20, 2024

Overview

This is a refactor of Cannon to support both 32-bit and 64-bit MIPS emulation while reusing code as much as possible.
A lot of the implementation was guided by the initial efforts in #11388 and @GrapeBaBa for anton-rs/cannon-rs#36.
The refactor prioritizes readability and avoids duplicating code to ensure that the 32-bit behavior is not altered. This is achieved by partitioning 64-bit and 32-bit logic using go build tags. The cannon32 and cannon64 build tags are used to implement architecture specific functionality. Most MIPS emulation logic can be factorized into common constructs with minimal loss in readability. For example, exec.SignExtend can be implemented across all VMs with the following:

func SignExtend(dat arch.Word, idx arch.Word) arch.Word {
        isSigned := (dat >> (idx - 1)) != 0
        signed := ((arch.Word(1) << (arch.WordSize - idx)) - 1) << idx
        mask := (arch.Word(1) << idx) - 1
        if isSigned {
                return dat&mask | signed
        } else {
                return dat & mask
        }
}

Where arch is a new cannon package that abstracts away the specifics of either MIPS32 or MIPS64.

One advantage of this approach is that MT-Cannon can be gradually ported over to MIPS64 without breaking the altering the existing code structure. Similarly, the single-threaded Cannon VM can be ported over to MIPS64 (though this isn't desired). This unlocks parallel development of 32 and 64 bit VMs.

This refactor does not affect the MIPS solidity contracts. The goal is to retain readability such that the refactored Go implementations can still be easily compared with the solidity counterparts. Introducing a 64-bit MIPS VM in Solidity will be done later.

Concerns

The downside of this approach is that both 32-bit and 64-bit VMs can no longer exist in the same Cannon binary. This breaks other packages, including the op-challenger, that rely on cannon packages for state decoding. Deployment of the op-challenger is further complicated as two VM binaries are needed for both single-threaded MIPS32 and MT-MIPS64 emulation. Fortunately this issue can be solved using multicannon which lets us select either 32-bit or 64-bit VM implementations depending on the CLI inputs.

Testing Plan

Note that the MIPS64 implementation is not complete. The primary goal of this PR is to ensure that the MIPS32 VM behaviors are not altered. Comprehensive MIPS64 testing will be added later.

  • Modify existing tests to assert MIPS32 functionality.
  • Differentially test the refactored cannon against the version on develop using a complex program (ex: op-program).
    • Done for simpler programs but not the op-program

Copy link
Contributor

semgrep-app bot commented Sep 20, 2024

Semgrep found 13 sol-style-notice-over-dev-natspec findings:

Prefer @notice over @dev in natspec comments

Ignore this finding from sol-style-notice-over-dev-natspec.

@ajsutton
Copy link
Contributor

Very cool idea. I think it's worth having a wrapper of some form so that op-challenger can just invoke cannon and have it just work. I'm trying to reduce the amount challenger has to understand about the VM states so would like to avoid the auto detection happening in challenger and otherwise we're back to needing a new game type which adds a bunch of unfortunate overhead. Hopefully that's not too hard to do because this looks like a pretty big win in being able to make incremental progress towards 64 bit and avoiding a lot of code duplication.

Copy link

codecov bot commented Sep 26, 2024

Codecov Report

Attention: Patch coverage is 65.04348% with 201 lines in your changes missing coverage. Please review.

Project coverage is 71.99%. Comparing base (d05fb50) to head (378e22e).
Report is 3 commits behind head on develop.

Files with missing lines Patch % Lines
cannon/mipsevm/exec/mips_instructions.go 46.12% 122 Missing and 3 partials ⚠️
cannon/mipsevm/versions/state.go 21.62% 24 Missing and 5 partials ⚠️
cannon/mipsevm/memory/memory.go 86.66% 3 Missing and 5 partials ⚠️
cannon/mipsevm/multithreaded/mips.go 80.00% 5 Missing and 2 partials ⚠️
cannon/mipsevm/exec/mips_syscalls.go 86.20% 4 Missing ⚠️
cannon/mipsevm/multithreaded/state.go 76.47% 2 Missing and 2 partials ⚠️
cannon/mipsevm/multithreaded/testutil/mutators.go 70.00% 3 Missing ⚠️
cannon/mipsevm/singlethreaded/instrumented.go 25.00% 2 Missing and 1 partial ⚠️
cannon/mipsevm/testutil/rand.go 72.72% 2 Missing and 1 partial ⚠️
cannon/mipsevm/testutil/state.go 70.00% 2 Missing and 1 partial ⚠️
... and 9 more
Additional details and impacted files
@@             Coverage Diff             @@
##           develop   #12029      +/-   ##
===========================================
- Coverage    75.19%   71.99%   -3.21%     
===========================================
  Files           49       50       +1     
  Lines         3665     3910     +245     
===========================================
+ Hits          2756     2815      +59     
- Misses         736      910     +174     
- Partials       173      185      +12     
Flag Coverage Δ
cannon-go-tests 71.99% <65.04%> (-3.21%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
cannon/mipsevm/arch/arch32.go 100.00% <100.00%> (ø)
cannon/mipsevm/exec/preimage.go 87.87% <100.00%> (ø)
cannon/mipsevm/exec/stack.go 66.66% <100.00%> (ø)
cannon/mipsevm/memory/page.go 66.21% <100.00%> (ø)
cannon/mipsevm/multithreaded/testutil/thread.go 99.15% <100.00%> (ø)
cannon/mipsevm/multithreaded/thread.go 61.17% <100.00%> (ø)
cannon/mipsevm/program/patch.go 86.56% <100.00%> (+2.63%) ⬆️
cannon/mipsevm/singlethreaded/mips.go 93.24% <100.00%> (ø)
cannon/mipsevm/singlethreaded/state.go 55.66% <100.00%> (ø)
cannon/mipsevm/state.go 100.00% <ø> (ø)
... and 23 more

... and 1 file with indirect coverage changes

@Inphi Inphi force-pushed the inphi/cannon-64-reorg branch 2 times, most recently from 65cc296 to 25886a3 Compare September 26, 2024 18:54
@Inphi Inphi marked this pull request as ready for review September 26, 2024 18:57
@Inphi Inphi requested review from a team as code owners September 26, 2024 18:57
Refactor Cannon codebase to support both 32-bit and 64-bit MIPS emulation
while reusing code as much as possible.
@Inphi Inphi removed the request for review from tynes September 26, 2024 22:00
Copy link
Contributor

semgrep-app bot commented Sep 27, 2024

Semgrep found 2 sol-style-require-reason findings:

require() must include a reason string

Ignore this finding from sol-style-require-reason.

Semgrep found 12 sol-safety-deployutils-args findings:

_args parameter should be wrapped with DeployUtils.encodeConstructor

Ignore this finding from sol-safety-deployutils-args.

Copy link
Member

@clabby clabby left a comment

Choose a reason for hiding this comment

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

This looks really good. Awesome job!

Approving as this looks good per the original 64-bit changes I made in #11388. Probably good to get eyes from @mbaxter + @ajsutton as well before merging + moving forward with the 64-bit smart contract from #11404.

P.S. - there's also some 64-bit ASM tests from #11388 we can use.

Copy link
Contributor

@ajsutton ajsutton left a comment

Choose a reason for hiding this comment

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

LGTM generally. I assume at some point we'll have 64bit MIPS reference tests we can pull in to verify each instruction is implemented correctly. That's quite hard to review manually.

Otherwise mostly just ensuring we have issues referenced for the TODOs (I'd just point them all to the 64-bit support tracker issue and not try to log individual issues for everything necessarily). And we'll have to sort out some conflicts with the getfd support but I don't think that will be a problem.

cannon/Makefile Outdated Show resolved Hide resolved
cannon/mipsevm/exec/mips_instructions.go Outdated Show resolved Hide resolved
cannon/mipsevm/exec/mips_instructions.go Outdated Show resolved Hide resolved
cannon/mipsevm/exec/mips_instructions.go Show resolved Hide resolved
cannon/mipsevm/exec/mips_instructions.go Outdated Show resolved Hide resolved
cannon/mipsevm/exec/mips_instructions.go Outdated Show resolved Hide resolved
cannon/mipsevm/exec/mips_syscalls.go Outdated Show resolved Hide resolved
cannon/mipsevm/multithreaded/mips.go Outdated Show resolved Hide resolved
cannon/mipsevm/versions/detect_test.go Outdated Show resolved Hide resolved
ops/docker/op-stack-go/Dockerfile.dockerignore Outdated Show resolved Hide resolved
Copy link
Contributor

@mbaxter mbaxter left a comment

Choose a reason for hiding this comment

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

Overall looks really good!

Would definitely be nice to get the additional differential tests in for extra confidence that none of the 32-bit behavior has changed. I did end up kind skimming over some of the new 64-bit ops - might try to spend some more time looking through those later.

cannon/Makefile Show resolved Hide resolved
cannon/Makefile Outdated Show resolved Hide resolved
cannon/Makefile Show resolved Hide resolved
cannon/mipsevm/multithreaded/state_test.go Outdated Show resolved Hide resolved
cannon/mipsevm/exec/mips_instructions.go Outdated Show resolved Hide resolved
cannon/mipsevm/program/load.go Outdated Show resolved Hide resolved
cannon/mipsevm/program/patch.go Outdated Show resolved Hide resolved
cannon/mipsevm/singlethreaded/state.go Outdated Show resolved Hide resolved
cannon/mipsevm/versions/state.go Show resolved Hide resolved
docker-bake.hcl Outdated Show resolved Hide resolved
Copy link
Contributor

semgrep-app bot commented Oct 1, 2024

Semgrep found 8 golang_fmt_errorf_no_params findings:

No fmt.Errorf invocations without fmt arguments allowed

Ignore this finding from golang_fmt_errorf_no_params.

Semgrep found 3 dangerous-exec-command findings:

Detected non-static command inside Command. Audit the input to 'exec.Command'. If unverified user data can reach this call site, this is a code injection vulnerability. A malicious actor can inject a malicious script to execute arbitrary code.

Ignore this finding from dangerous-exec-command.

@Inphi Inphi requested a review from mbaxter October 1, 2024 18:19
@Inphi
Copy link
Contributor Author

Inphi commented Oct 1, 2024

@mbaxter I've kicked off the cannon-stf-verify job to assert that this change doesn't break the VM STF. It uses this PR and cannon/v1.1.0-alpha.1 to compute the post-exit state of the hello.go program and compares the results. It passes which provides some confidence that we haven't broken anything.

@Inphi Inphi enabled auto-merge October 1, 2024 18:36
@Inphi Inphi added this pull request to the merge queue Oct 1, 2024
Merged via the queue into develop with commit a2653a3 Oct 1, 2024
66 of 69 checks passed
@Inphi Inphi deleted the inphi/cannon-64-reorg branch October 1, 2024 18:47
samlaf pushed a commit to samlaf/optimism that referenced this pull request Nov 10, 2024
* cannon: 64-bit Refactor

Refactor Cannon codebase to support both 32-bit and 64-bit MIPS emulation
while reusing code as much as possible.

* fix 64-bit test compilation errors

* review comments

* more review comments

* fcntl syscall err for 64-bit

* simplify pad check

* cannon: sc must store lsb 32 on 64-bits

* lint

* fix sc 64-bit logic

* add TODO state test
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.

4 participants