Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/develop' into holocene-1559
Browse files Browse the repository at this point in the history
  • Loading branch information
mslipper committed Oct 21, 2024
2 parents e6c5527 + 76c1e1d commit 02a63d9
Show file tree
Hide file tree
Showing 120 changed files with 18,843 additions and 1,313 deletions.
21 changes: 18 additions & 3 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -796,9 +796,22 @@ jobs:
description: Test directory
type: string
default: "./..."
machine: true
resource_class: ethereum-optimism/latitude-1
machine:
image: <<pipeline.parameters.base_image>>
resource_class: xlarge
steps:
- run:
name: Install components
command: |
go version
go install gotest.tools/[email protected]
- run:
name: Install Kurtosis
command: |
echo "deb [trusted=yes] https://apt.fury.io/kurtosis-tech/ /" | sudo tee /etc/apt/sources.list.d/kurtosis.list
sudo apt update
sudo apt install kurtosis-cli=1.3.0
kurtosis engine start
- checkout
- when:
condition: <<parameters.uses_artifacts>>
Expand Down Expand Up @@ -1291,7 +1304,7 @@ jobs:
- run:
name: Run goreleaser
command: |
./bin/goreleaser release --clean -f ./<<parameters.module>>/<<parameters.filename>>
goreleaser release --clean -f ./<<parameters.module>>/<<parameters.filename>>
workflows:
main:
Expand Down Expand Up @@ -1462,6 +1475,8 @@ workflows:
branches:
ignore: /.*/
module: op-deployer
context:
- oplabs-gcr-release

release:
when:
Expand Down
10 changes: 10 additions & 0 deletions .semgrep/sol-rules.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ rules:
paths:
exclude:
- op-chain-ops/script/testdata/scripts/ScriptExample.s.sol
- packages/contracts-bedrock/test
- packages/contracts-bedrock/scripts/libraries/Solarray.sol
- packages/contracts-bedrock/scripts/interfaces/IGnosisSafe.sol
- packages/contracts-bedrock/src/universal/interfaces/IWETH.sol
Expand All @@ -30,6 +31,7 @@ rules:
paths:
exclude:
- op-chain-ops/script/testdata/scripts/ScriptExample.s.sol
- packages/contracts-bedrock/test
- packages/contracts-bedrock/scripts/libraries/Solarray.sol
- packages/contracts-bedrock/scripts/interfaces/IGnosisSafe.sol
- packages/contracts-bedrock/src/dispute/interfaces/IPermissionedDisputeGame.sol
Expand All @@ -40,13 +42,19 @@ rules:
severity: ERROR
message: Javadoc-style comments are not allowed, use `///` style doc comments instead
pattern-regex: (\/\*\*\n(\s+\*\s.*\n)+\s+\*\/)
paths:
exclude:
- packages/contracts-bedrock/test

- id: sol-expectrevert-no-args
languages: [solidity]
severity: ERROR
message: vm.expectRevert() must specify the revert reason
patterns:
- pattern: vm.expectRevert()
paths:
exclude:
- packages/contracts-bedrock/test

- id: sol-style-malformed-require
languages: [solidity]
Expand All @@ -62,6 +70,7 @@ rules:
- pattern-not-regex: \"([a-zA-Z0-9\s]+-[a-zA-Z0-9\s]+-[a-zA-Z0-9\s]+)\"
paths:
exclude:
- packages/contracts-bedrock/test
- packages/contracts-bedrock/src/libraries/Bytes.sol
- packages/contracts-bedrock/src/legacy/LegacyMintableERC20.sol
- packages/contracts-bedrock/src/cannon/MIPS.sol
Expand All @@ -80,4 +89,5 @@ rules:
- pattern-not-regex: \"(\w+:\s[^"]+)\"
paths:
exclude:
- packages/contracts-bedrock/test
- packages/contracts-bedrock/src/cannon/libraries/MIPSInstructions.sol
5 changes: 0 additions & 5 deletions .semgrepignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,6 @@ vendor/
.tox/
*.min.js

# Common test paths
# TODO: Tests should conform to semgrep too.
test/
tests/

# Semgrep rules folder
.semgrep

Expand Down
4 changes: 0 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -186,10 +186,6 @@ devnet-up: pre-devnet ## Starts the local devnet
PYTHONPATH=./bedrock-devnet $(PYTHON) ./bedrock-devnet/main.py --monorepo-dir=.
.PHONY: devnet-up

devnet-test: pre-devnet ## Runs tests on the local devnet
make -C op-e2e test-devnet
.PHONY: devnet-test

devnet-down: ## Stops the local devnet
@(cd ./ops-bedrock && GENESIS_TIMESTAMP=$(shell date +%s) docker compose stop)
.PHONY: devnet-down
Expand Down
2 changes: 1 addition & 1 deletion bedrock-devnet/devnet/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,8 @@ def devnet_deploy(paths):
# Selectively set the L2OO_ADDRESS or DGF_ADDRESS if using L2OO.
# Must be done selectively because op-proposer throws if both are set.
if DEVNET_L2OO:
docker_env['L2OO_ADDRESS'] = l2_output_oracle
l2_output_oracle = addresses['L2OutputOracleProxy']
docker_env['L2OO_ADDRESS'] = l2_output_oracle
log.info(f'Using L2OutputOracle {l2_output_oracle}')
else:
dispute_game_factory = addresses['DisputeGameFactoryProxy']
Expand Down
44 changes: 44 additions & 0 deletions cannon/mipsevm/exec/mips_instructions.go
Original file line number Diff line number Diff line change
Expand Up @@ -569,3 +569,47 @@ func HandleRd(cpu *mipsevm.CpuScalars, registers *[32]Word, storeReg Word, val W
cpu.NextPC = cpu.NextPC + 4
return nil
}

func LoadSubWord(memory *memory.Memory, addr Word, byteLength Word, signExtend bool, memoryTracker MemTracker) Word {
// Pull data from memory
effAddr := (addr) & arch.AddressMask
memoryTracker.TrackMemAccess(effAddr)
mem := memory.GetWord(effAddr)

// Extract a sub-word based on the low-order bits in addr
dataMask, bitOffset, bitLength := calculateSubWordMaskAndOffset(addr, byteLength)
retVal := (mem >> bitOffset) & dataMask
if signExtend {
retVal = SignExtend(retVal, bitLength)
}

return retVal
}

func StoreSubWord(memory *memory.Memory, addr Word, byteLength Word, value Word, memoryTracker MemTracker) {
// Pull data from memory
effAddr := (addr) & arch.AddressMask
memoryTracker.TrackMemAccess(effAddr)
mem := memory.GetWord(effAddr)

// Modify isolated sub-word within mem
dataMask, bitOffset, _ := calculateSubWordMaskAndOffset(addr, byteLength)
subWordValue := dataMask & value
memUpdateMask := dataMask << bitOffset
newMemVal := subWordValue<<bitOffset | (^memUpdateMask)&mem

memory.SetWord(effAddr, newMemVal)
}

func calculateSubWordMaskAndOffset(addr Word, byteLength Word) (dataMask, bitOffset, bitLength Word) {
bitLength = byteLength << 3
dataMask = ^Word(0) >> (arch.WordSize - bitLength)

// Figure out sub-word index based on the low-order bits in addr
byteIndexMask := addr & arch.ExtMask & ^(byteLength - 1)
maxByteShift := arch.WordSizeBytes - byteLength
byteIndex := addr & byteIndexMask
bitOffset = (maxByteShift - byteIndex) << 3

return dataMask, bitOffset, bitLength
}
110 changes: 110 additions & 0 deletions cannon/mipsevm/exec/mips_instructions32_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// These tests target architectures that are 32-bit or larger
package exec

import (
"testing"

"github.com/stretchr/testify/require"

"github.com/ethereum-optimism/optimism/cannon/mipsevm/arch"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/memory"
)

// TestLoadSubWord_32bits validates LoadSubWord with 32-bit offsets (up to 3 bytes)
func TestLoadSubWord_32bits(t *testing.T) {
cases := []struct {
name string
byteLength Word
addr uint32
memVal uint32
signExtend bool
shouldSignExtend bool
expectedValue uint32
}{
{name: "32-bit", byteLength: 4, addr: 0xFF00_0000, memVal: 0x1234_5678, expectedValue: 0x1234_5678},
{name: "32-bit, extra bits", byteLength: 4, addr: 0xFF00_0001, memVal: 0x1234_5678, expectedValue: 0x1234_5678},
{name: "32-bit, extra bits", byteLength: 4, addr: 0xFF00_0002, memVal: 0x1234_5678, expectedValue: 0x1234_5678},
{name: "32-bit, extra bits", byteLength: 4, addr: 0xFF00_0003, memVal: 0x1234_5678, expectedValue: 0x1234_5678},
{name: "16-bit, offset=0", byteLength: 2, addr: 0x00, memVal: 0x1234_5678, expectedValue: 0x1234},
{name: "16-bit, offset=0, extra bit set", byteLength: 2, addr: 0x01, memVal: 0x1234_5678, expectedValue: 0x1234},
{name: "16-bit, offset=2", byteLength: 2, addr: 0x02, memVal: 0x1234_5678, expectedValue: 0x5678},
{name: "16-bit, offset=2, extra bit set", byteLength: 2, addr: 0x03, memVal: 0x1234_5678, expectedValue: 0x5678},
{name: "16-bit, sign extend positive val", byteLength: 2, addr: 0x02, memVal: 0x1234_5678, expectedValue: 0x5678, signExtend: true, shouldSignExtend: false},
{name: "16-bit, sign extend negative val", byteLength: 2, addr: 0x02, memVal: 0x1234_F678, expectedValue: 0xFFFF_F678, signExtend: true, shouldSignExtend: true},
{name: "16-bit, do not sign extend negative val", byteLength: 2, addr: 0x02, memVal: 0x1234_F678, expectedValue: 0xF678, signExtend: false},
{name: "8-bit, offset=0", byteLength: 1, addr: 0x1230, memVal: 0x1234_5678, expectedValue: 0x12},
{name: "8-bit, offset=1", byteLength: 1, addr: 0x1231, memVal: 0x1234_5678, expectedValue: 0x34},
{name: "8-bit, offset=2", byteLength: 1, addr: 0x1232, memVal: 0x1234_5678, expectedValue: 0x56},
{name: "8-bit, offset=3", byteLength: 1, addr: 0x1233, memVal: 0x1234_5678, expectedValue: 0x78},
{name: "8-bit, sign extend positive", byteLength: 1, addr: 0x1233, memVal: 0x1234_5678, expectedValue: 0x78, signExtend: true, shouldSignExtend: false},
{name: "8-bit, sign extend negative", byteLength: 1, addr: 0x1233, memVal: 0x1234_5688, expectedValue: 0xFFFF_FF88, signExtend: true, shouldSignExtend: true},
{name: "8-bit, do not sign extend neg value", byteLength: 1, addr: 0x1233, memVal: 0x1234_5688, expectedValue: 0x88, signExtend: false},
}

for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
mem := memory.NewMemory()
memTracker := NewMemoryTracker(mem)

effAddr := Word(c.addr) & arch.AddressMask
// Shift memval for consistency across architectures
memVal := Word(c.memVal) << (arch.WordSize - 32)
mem.SetWord(effAddr, memVal)

retVal := LoadSubWord(mem, Word(c.addr), c.byteLength, c.signExtend, memTracker)

// If sign extending, make sure retVal is consistent across architectures
expected := Word(c.expectedValue)
if c.shouldSignExtend {
signedBits := ^Word(0xFFFF_FFFF)
expected = expected | signedBits
}
require.Equal(t, expected, retVal)
})
}
}

// TestStoreSubWord_32bits validates LoadSubWord with 32-bit offsets (up to 3 bytes)
func TestStoreSubWord_32bits(t *testing.T) {
memVal := 0xFFFF_FFFF
value := 0x1234_5678

cases := []struct {
name string
byteLength Word
addr uint32
expectedValue uint32
}{
{name: "32-bit", byteLength: 4, addr: 0xFF00_0000, expectedValue: 0x1234_5678},
{name: "32-bit, extra bits", byteLength: 4, addr: 0xFF00_0001, expectedValue: 0x1234_5678},
{name: "32-bit, extra bits", byteLength: 4, addr: 0xFF00_0002, expectedValue: 0x1234_5678},
{name: "32-bit, extra bits", byteLength: 4, addr: 0xFF00_0003, expectedValue: 0x1234_5678},
{name: "16-bit, subword offset=0", byteLength: 2, addr: 0x00, expectedValue: 0x5678_FFFF},
{name: "16-bit, subword offset=0, extra bit set", byteLength: 2, addr: 0x01, expectedValue: 0x5678_FFFF},
{name: "16-bit, subword offset=2", byteLength: 2, addr: 0x02, expectedValue: 0xFFFF_5678},
{name: "16-bit, subword offset=2, extra bit set", byteLength: 2, addr: 0x03, expectedValue: 0xFFFF_5678},
{name: "8-bit, offset=0", byteLength: 1, addr: 0x1230, expectedValue: 0x78FF_FFFF},
{name: "8-bit, offset=1", byteLength: 1, addr: 0x1231, expectedValue: 0xFF78_FFFF},
{name: "8-bit, offset=2", byteLength: 1, addr: 0x1232, expectedValue: 0xFFFF_78FF},
{name: "8-bit, offset=3", byteLength: 1, addr: 0x1233, expectedValue: 0xFFFF_FF78},
}

for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
mem := memory.NewMemory()
memTracker := NewMemoryTracker(mem)

effAddr := Word(c.addr) & arch.AddressMask
// Shift memval for consistency across architectures
memVal := Word(memVal) << (arch.WordSize - 32)
mem.SetWord(effAddr, memVal)

StoreSubWord(mem, Word(c.addr), c.byteLength, Word(value), memTracker)
newMemVal := mem.GetWord(effAddr)

// Make sure expectation is consistent across architectures
expected := Word(c.expectedValue) << (arch.WordSize - 32)
require.Equal(t, expected, newMemVal)
})
}
}
111 changes: 111 additions & 0 deletions cannon/mipsevm/exec/mips_instructions64_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
//go:build cannon64
// +build cannon64

// These tests target architectures that are 64-bit or larger
package exec

import (
"testing"

"github.com/stretchr/testify/require"

"github.com/ethereum-optimism/optimism/cannon/mipsevm/arch"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/memory"
)

// TestLoadSubWord_64bits extends TestLoadSubWord_32bits by testing up to 64-bits (7 byte) offsets
func TestLoadSubWord_64bits(t *testing.T) {
memVal := uint64(0x1234_5678_9876_5432)
cases := []struct {
name string
byteLength Word
addr uint64
memVal uint64
signExtend bool
expectedValue uint64
}{
{name: "64-bit", byteLength: 8, addr: 0xFF00_0000, memVal: 0x8234_5678_9876_5432, expectedValue: 0x8234_5678_9876_5432},
{name: "64-bit w sign extension", byteLength: 8, addr: 0xFF00_0000, memVal: 0x8234_5678_9876_5432, expectedValue: 0x8234_5678_9876_5432, signExtend: true},
{name: "32-bit, offset=0", byteLength: 4, addr: 0xFF00_0000, memVal: memVal, expectedValue: 0x1234_5678},
{name: "32-bit, offset=0, extra bits", byteLength: 4, addr: 0xFF00_0001, memVal: memVal, expectedValue: 0x1234_5678},
{name: "32-bit, offset=0, extra bits", byteLength: 4, addr: 0xFF00_0002, memVal: memVal, expectedValue: 0x1234_5678},
{name: "32-bit, offset=0, extra bits", byteLength: 4, addr: 0xFF00_0003, memVal: memVal, expectedValue: 0x1234_5678},
{name: "32-bit, offset=4", byteLength: 4, addr: 0xFF00_0004, memVal: memVal, expectedValue: 0x9876_5432},
{name: "32-bit, offset=4, extra bits", byteLength: 4, addr: 0xFF00_0005, memVal: memVal, expectedValue: 0x9876_5432},
{name: "32-bit, offset=4, extra bits", byteLength: 4, addr: 0xFF00_0006, memVal: memVal, expectedValue: 0x9876_5432},
{name: "32-bit, offset=4, extra bits", byteLength: 4, addr: 0xFF00_0007, memVal: memVal, expectedValue: 0x9876_5432},
{name: "32-bit, sign extend negative", byteLength: 4, addr: 0xFF00_0006, memVal: 0x1234_5678_F1E2_A1B1, expectedValue: 0xFFFF_FFFF_F1E2_A1B1, signExtend: true},
{name: "32-bit, sign extend positive", byteLength: 4, addr: 0xFF00_0007, memVal: 0x1234_5678_7876_5432, expectedValue: 0x7876_5432, signExtend: true},
{name: "16-bit, subword offset=4", byteLength: 2, addr: 0x04, memVal: memVal, expectedValue: 0x9876},
{name: "16-bit, subword offset=4, extra bit set", byteLength: 2, addr: 0x05, memVal: memVal, expectedValue: 0x9876},
{name: "16-bit, subword offset=6", byteLength: 2, addr: 0x06, memVal: memVal, expectedValue: 0x5432},
{name: "16-bit, subword offset=6, extra bit set", byteLength: 2, addr: 0x07, memVal: memVal, expectedValue: 0x5432},
{name: "16-bit, sign extend negative val", byteLength: 2, addr: 0x04, memVal: 0x1234_5678_8BEE_CCDD, expectedValue: 0xFFFF_FFFF_FFFF_8BEE, signExtend: true},
{name: "16-bit, sign extend positive val", byteLength: 2, addr: 0x04, memVal: 0x1234_5678_7876_5432, expectedValue: 0x7876, signExtend: true},
{name: "8-bit, offset=4", byteLength: 1, addr: 0x1234, memVal: memVal, expectedValue: 0x98},
{name: "8-bit, offset=5", byteLength: 1, addr: 0x1235, memVal: memVal, expectedValue: 0x76},
{name: "8-bit, offset=6", byteLength: 1, addr: 0x1236, memVal: memVal, expectedValue: 0x54},
{name: "8-bit, offset=7", byteLength: 1, addr: 0x1237, memVal: memVal, expectedValue: 0x32},
{name: "8-bit, sign extend positive", byteLength: 1, addr: 0x1237, memVal: memVal, expectedValue: 0x32, signExtend: true},
{name: "8-bit, sign extend negative", byteLength: 1, addr: 0x1237, memVal: 0x1234_5678_8764_4381, expectedValue: 0xFFFF_FFFF_FFFF_FF81, signExtend: true},
}

for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
mem := memory.NewMemory()
memTracker := NewMemoryTracker(mem)

effAddr := Word(c.addr) & arch.AddressMask
mem.SetWord(effAddr, c.memVal)

retVal := LoadSubWord(mem, Word(c.addr), c.byteLength, c.signExtend, memTracker)
require.Equal(t, c.expectedValue, retVal)
})
}
}

// TestStoreSubWord_64bits extends TestStoreSubWord_32bits by testing up to 64-bits (7 byte) offsets
func TestStoreSubWord_64bits(t *testing.T) {
memVal := uint64(0xFFFF_FFFF_FFFF_FFFF)
value := uint64(0x1234_5678_9876_5432)

cases := []struct {
name string
byteLength Word
addr uint64
expectedValue uint64
}{
{name: "64-bit", byteLength: 8, addr: 0xFF00_0000, expectedValue: value},
{name: "32-bit, offset 0", byteLength: 4, addr: 0xFF00_0000, expectedValue: 0x9876_5432_FFFF_FFFF},
{name: "32-bit, offset 0, extra addr bits", byteLength: 4, addr: 0xFF00_0001, expectedValue: 0x9876_5432_FFFF_FFFF},
{name: "32-bit, offset 0, extra addr bits", byteLength: 4, addr: 0xFF00_0002, expectedValue: 0x9876_5432_FFFF_FFFF},
{name: "32-bit, offset 0, extra addr bits", byteLength: 4, addr: 0xFF00_0003, expectedValue: 0x9876_5432_FFFF_FFFF},
{name: "32-bit, offset 4", byteLength: 4, addr: 0xFF00_0004, expectedValue: 0xFFFF_FFFF_9876_5432},
{name: "32-bit, offset 4, extra addr bits", byteLength: 4, addr: 0xFF00_0005, expectedValue: 0xFFFF_FFFF_9876_5432},
{name: "32-bit, offset 4, extra addr bits", byteLength: 4, addr: 0xFF00_0006, expectedValue: 0xFFFF_FFFF_9876_5432},
{name: "32-bit, offset 4, extra addr bits", byteLength: 4, addr: 0xFF00_0007, expectedValue: 0xFFFF_FFFF_9876_5432},
{name: "16-bit, offset=4", byteLength: 2, addr: 0x04, expectedValue: 0xFFFF_FFFF_5432_FFFF},
{name: "16-bit, offset=4, extra bit set", byteLength: 2, addr: 0x05, expectedValue: 0xFFFF_FFFF_5432_FFFF},
{name: "16-bit, offset=6", byteLength: 2, addr: 0x06, expectedValue: 0xFFFF_FFFF_FFFF_5432},
{name: "16-bit, offset=6, extra bit set", byteLength: 2, addr: 0x07, expectedValue: 0xFFFF_FFFF_FFFF_5432},
{name: "8-bit, offset=4", byteLength: 1, addr: 0x1234, expectedValue: 0xFFFF_FFFF_32FF_FFFF},
{name: "8-bit, offset=5", byteLength: 1, addr: 0x1235, expectedValue: 0xFFFF_FFFF_FF32_FFFF},
{name: "8-bit, offset=6", byteLength: 1, addr: 0x1236, expectedValue: 0xFFFF_FFFF_FFFF_32FF},
{name: "8-bit, offset=7", byteLength: 1, addr: 0x1237, expectedValue: 0xFFFF_FFFF_FFFF_FF32},
}

for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
mem := memory.NewMemory()
memTracker := NewMemoryTracker(mem)

effAddr := Word(c.addr) & arch.AddressMask
mem.SetWord(effAddr, memVal)

StoreSubWord(mem, Word(c.addr), c.byteLength, Word(value), memTracker)
newMemVal := mem.GetWord(effAddr)

require.Equal(t, c.expectedValue, newMemVal)
})
}
}
Loading

0 comments on commit 02a63d9

Please sign in to comment.