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
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 26 additions & 8 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,9 @@ jobs:
description: Whether to notify on failure
type: boolean
default: false
mips64:
type: boolean
default: false
resource_class: xlarge
steps:
- checkout
Expand All @@ -184,14 +187,29 @@ jobs:
command: |
make lint
working_directory: cannon
- run:
name: Cannon Go tests
command: |
export SKIP_SLOW_TESTS=<<parameters.skip_slow_tests>>
mkdir -p /testlogs
gotestsum --format=testname --junitfile=/tmp/test-results/cannon.xml --jsonfile=/testlogs/log.json \
-- -parallel=8 -coverpkg=github.com/ethereum-optimism/optimism/cannon/... -coverprofile=coverage.out ./...
working_directory: cannon
- when:
condition:
not: <<parameters.mips64>>
steps:
- run:
name: Cannon Go 32-bit tests
command: |
export SKIP_SLOW_TESTS=<<parameters.skip_slow_tests>>
mkdir -p /testlogs
gotestsum --format=testname --junitfile=/tmp/test-results/cannon.xml --jsonfile=/testlogs/log.json \
-- -parallel=8 -coverpkg=github.com/ethereum-optimism/optimism/cannon/... -coverprofile=coverage.out ./...
working_directory: cannon
- when:
condition: <<parameters.mips64>>
steps:
- run:
name: Cannon Go 64-bit tests
command: |
export SKIP_SLOW_TESTS=<<parameters.skip_slow_tests>>
mkdir -p /testlogs
gotestsum --format=testname --junitfile=/tmp/test-results/cannon.xml --jsonfile=/testlogs/log.json \
-- --tags=cannon64 -parallel=8 -coverpkg=github.com/ethereum-optimism/optimism/cannon/... -coverprofile=coverage.out ./...
working_directory: cannon
- run:
name: upload Cannon coverage
command: codecov --verbose --clean --flags cannon-go-tests
Expand Down
19 changes: 13 additions & 6 deletions cannon/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,22 @@ endif

.DEFAULT_GOAL := cannon

cannon-impl:
env GO111MODULE=on GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) go build -v $(LDFLAGS) -o ./bin/cannon-impl .
cannon32-impl:
env GO111MODULE=on GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) go build --tags=cannon32 -v $(LDFLAGS) -o ./bin/cannon32-impl .
Inphi marked this conversation as resolved.
Show resolved Hide resolved

cannon-embeds: cannon-impl
@cp bin/cannon-impl ./multicannon/embeds/cannon-0
@cp bin/cannon-impl ./multicannon/embeds/cannon-1
cannon64-impl:
env GO111MODULE=on GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) go build --tags=cannon64 -v $(LDFLAGS) -o ./bin/cannon64-impl .

cannon-embeds: cannon32-impl cannon64-impl
@cp bin/cannon32-impl ./multicannon/embeds/cannon-0
@cp bin/cannon32-impl ./multicannon/embeds/cannon-1
@cp bin/cannon64-impl ./multicannon/embeds/cannon-2
Inphi marked this conversation as resolved.
Show resolved Hide resolved

cannon: cannon-embeds
env GO111MODULE=on GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) go build -v $(LDFLAGS) -o ./bin/cannon ./multicannon/

clean:
rm -rf bin
rm -rf bin multicannon/embeds/cannon*

elf:
make -C ./testdata/example elf
Expand Down Expand Up @@ -81,6 +85,9 @@ fuzz:
go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzStateSyscallCloneMT ./mipsevm/tests

.PHONY: \
cannon32-impl \
cannon64-impl \
cannon-embeds \
Inphi marked this conversation as resolved.
Show resolved Hide resolved
cannon \
cannon-impl \
Inphi marked this conversation as resolved.
Show resolved Hide resolved
cannon-embeds \
Expand Down
4 changes: 2 additions & 2 deletions cannon/cmd/load_elf.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ var (
}
LoadELFPathFlag = &cli.PathFlag{
Name: "path",
Usage: "Path to 32-bit big-endian MIPS ELF file",
Usage: "Path to 32/64-bit big-endian MIPS ELF file",
TakesFile: true,
Required: true,
}
Expand Down Expand Up @@ -80,7 +80,7 @@ func LoadELF(ctx *cli.Context) error {
}
return program.PatchStack(state)
}
case versions.VersionMultiThreaded:
case versions.VersionMultiThreaded, versions.VersionMultiThreaded64:
createInitialState = func(f *elf.File) (mipsevm.FPVMState, error) {
return program.LoadELF(f, multithreaded.CreateInitialState)
}
Expand Down
20 changes: 10 additions & 10 deletions cannon/cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,19 @@ import (
"strings"
"time"

"github.com/ethereum-optimism/optimism/cannon/mipsevm"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/arch"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/program"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/versions"
"github.com/ethereum-optimism/optimism/cannon/serialize"
preimage "github.com/ethereum-optimism/optimism/op-preimage"
"github.com/ethereum-optimism/optimism/op-service/ioutil"
"github.com/ethereum-optimism/optimism/op-service/jsonutil"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/log"
"github.com/pkg/profile"
"github.com/urfave/cli/v2"

"github.com/ethereum-optimism/optimism/cannon/mipsevm"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/program"
preimage "github.com/ethereum-optimism/optimism/op-preimage"
"github.com/ethereum-optimism/optimism/op-service/jsonutil"
)

var (
Expand Down Expand Up @@ -128,7 +128,7 @@ type Proof struct {

OracleKey hexutil.Bytes `json:"oracle-key,omitempty"`
OracleValue hexutil.Bytes `json:"oracle-value,omitempty"`
OracleOffset uint32 `json:"oracle-offset,omitempty"`
OracleOffset arch.Word `json:"oracle-offset,omitempty"`
}

type rawHint string
Expand Down Expand Up @@ -288,7 +288,7 @@ func Run(ctx *cli.Context) error {

stopAtAnyPreimage := false
var stopAtPreimageKeyPrefix []byte
stopAtPreimageOffset := uint32(0)
stopAtPreimageOffset := arch.Word(0)
if ctx.IsSet(RunStopAtPreimageFlag.Name) {
val := ctx.String(RunStopAtPreimageFlag.Name)
parts := strings.Split(val, "@")
Expand All @@ -297,11 +297,11 @@ func Run(ctx *cli.Context) error {
}
stopAtPreimageKeyPrefix = common.FromHex(parts[0])
if len(parts) == 2 {
x, err := strconv.ParseUint(parts[1], 10, 32)
x, err := strconv.ParseUint(parts[1], 10, arch.WordSizeBytes)
if err != nil {
return fmt.Errorf("invalid preimage offset: %w", err)
}
stopAtPreimageOffset = uint32(x)
stopAtPreimageOffset = arch.Word(x)
}
} else {
switch ctx.String(RunStopAtPreimageTypeFlag.Name) {
Expand Down Expand Up @@ -462,7 +462,7 @@ func Run(ctx *cli.Context) error {
}

lastPreimageKey, lastPreimageValue, lastPreimageOffset := vm.LastPreimage()
if lastPreimageOffset != ^uint32(0) {
if lastPreimageOffset != ^arch.Word(0) {
if stopAtAnyPreimage {
l.Info("Stopping at preimage read")
break
Expand Down
2 changes: 1 addition & 1 deletion cannon/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (

func main() {
app := cli.NewApp()
app.Name = "cannon"
app.Name = os.Args[0]
app.Usage = "MIPS Fault Proof tool"
app.Description = "MIPS Fault Proof tool"
app.Commands = []*cli.Command{
Expand Down
48 changes: 48 additions & 0 deletions cannon/mipsevm/arch/arch32.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//go:build !cannon64
// +build !cannon64

package arch

import "encoding/binary"

type (
// Word differs from the tradditional meaning in MIPS. The type represents the *maximum* architecture specific access length and value sizes.
Word = uint32
// SignedInteger specifies the maximum signed integer type used for arithmetic.
SignedInteger = int32
)

const (
IsMips32 = true
WordSize = 32
WordSizeBytes = WordSize >> 3
PageAddrSize = 12
PageKeySize = WordSize - PageAddrSize

MemProofLeafCount = 28
MemProofSize = MemProofLeafCount * 32

AddressMask = 0xFFffFFfc
ExtMask = 0x3

HeapStart = 0x05_00_00_00
HeapEnd = 0x60_00_00_00
ProgramBreak = 0x40_00_00_00
HighMemoryStart = 0x7f_ff_d0_00
)

var ByteOrderWord = byteOrder32{}

type byteOrder32 struct{}

func (bo byteOrder32) Word(b []byte) Word {
return binary.BigEndian.Uint32(b)
}

func (bo byteOrder32) AppendWord(b []byte, v uint32) []byte {
return binary.BigEndian.AppendUint32(b, v)
}

func (bo byteOrder32) PutWord(b []byte, v uint32) {
binary.BigEndian.PutUint32(b, v)
}
48 changes: 48 additions & 0 deletions cannon/mipsevm/arch/arch64.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//go:build cannon64
// +build cannon64

package arch

import "encoding/binary"

type (
// Word differs from the tradditional meaning in MIPS. The type represents the *maximum* architecture specific access length and value sizes
Word = uint64
// SignedInteger specifies the maximum signed integer type used for arithmetic.
SignedInteger = int64
)

const (
IsMips32 = false
WordSize = 64
WordSizeBytes = WordSize >> 3
PageAddrSize = 12
PageKeySize = WordSize - PageAddrSize

MemProofLeafCount = 60
MemProofSize = MemProofLeafCount * 32

AddressMask = 0xFFFFFFFFFFFFFFF8
ExtMask = 0x7

HeapStart = 0x10_00_00_00_00_00_00_00
HeapEnd = 0x60_00_00_00_00_00_00_00
ProgramBreak = 0x40_00_00_00_00_00_00_00
HighMemoryStart = 0x7F_FF_FF_FF_D0_00_00_00
)

var ByteOrderWord = byteOrder64{}

type byteOrder64 struct{}

func (bo byteOrder64) Word(b []byte) Word {
return binary.BigEndian.Uint64(b)
}

func (bo byteOrder64) AppendWord(b []byte, v uint64) []byte {
return binary.BigEndian.AppendUint64(b, v)
}

func (bo byteOrder64) PutWord(b []byte, v uint64) {
binary.BigEndian.PutUint64(b, v)
}
7 changes: 7 additions & 0 deletions cannon/mipsevm/arch/byteorder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package arch

type ByteOrder interface {
Word([]byte) Word
AppendWord([]byte, Word) []byte
PutWord([]byte, Word)
}
12 changes: 6 additions & 6 deletions cannon/mipsevm/exec/memory.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import (
)

type MemTracker interface {
TrackMemAccess(addr uint32)
TrackMemAccess(addr Word)
}

type MemoryTrackerImpl struct {
memory *memory.Memory
lastMemAccess uint32
lastMemAccess Word
memProofEnabled bool
// proof of first unique memory access
memProof [memory.MEM_PROOF_SIZE]byte
Expand All @@ -24,9 +24,9 @@ func NewMemoryTracker(memory *memory.Memory) *MemoryTrackerImpl {
return &MemoryTrackerImpl{memory: memory}
}

func (m *MemoryTrackerImpl) TrackMemAccess(effAddr uint32) {
func (m *MemoryTrackerImpl) TrackMemAccess(effAddr Word) {
if m.memProofEnabled && m.lastMemAccess != effAddr {
if m.lastMemAccess != ^uint32(0) {
if m.lastMemAccess != ^Word(0) {
panic(fmt.Errorf("unexpected different mem access at %08x, already have access at %08x buffered", effAddr, m.lastMemAccess))
}
m.lastMemAccess = effAddr
Expand All @@ -36,7 +36,7 @@ func (m *MemoryTrackerImpl) TrackMemAccess(effAddr uint32) {

// TrackMemAccess2 creates a proof for a memory access following a call to TrackMemAccess
// This is used to generate proofs for contiguous memory accesses within the same step
func (m *MemoryTrackerImpl) TrackMemAccess2(effAddr uint32) {
func (m *MemoryTrackerImpl) TrackMemAccess2(effAddr Word) {
if m.memProofEnabled && m.lastMemAccess+4 != effAddr {
panic(fmt.Errorf("unexpected disjointed mem access at %08x, last memory access is at %08x buffered", effAddr, m.lastMemAccess))
}
Expand All @@ -46,7 +46,7 @@ func (m *MemoryTrackerImpl) TrackMemAccess2(effAddr uint32) {

func (m *MemoryTrackerImpl) Reset(enableProof bool) {
m.memProofEnabled = enableProof
m.lastMemAccess = ^uint32(0)
m.lastMemAccess = ^Word(0)
}

func (m *MemoryTrackerImpl) MemProof() [memory.MEM_PROOF_SIZE]byte {
Expand Down
Loading