Skip to content

Commit

Permalink
Merge pull request #4 from OffchainLabs/eof-machinery
Browse files Browse the repository at this point in the history
Include EOF Machinery To Differentiate Stylus Programs from EVM Bytecode
  • Loading branch information
rachel-bousfield authored Jan 18, 2023
2 parents 1c0be5f + ea29f9c commit c4fc7d6
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 1 deletion.
10 changes: 9 additions & 1 deletion core/state/statedb_arbitrum.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ import (

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
)

func (s *StateDB) Deterministic() bool {
Expand Down Expand Up @@ -78,9 +80,15 @@ func (s *StateDB) RecordProgram(program common.Address, version uint32) {
if _, ok := s.userWasms[call]; ok {
return
}
rawCode := s.GetCode(program)
compressedWasm, err := vm.StripStylusPrefix(rawCode)
if err != nil {
log.Error("Could not strip stylus program prefix from raw code: %v", err)
return
}
s.userWasms[call] = &UserWasm{
NoncanonicalHash: s.NoncanonicalProgramHash(program, version),
CompressedWasm: s.GetCode(program),
CompressedWasm: compressedWasm,
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions core/vm/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,11 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
// Reject code starting with 0xEF if EIP-3541 is enabled.
if err == nil && len(ret) >= 1 && ret[0] == 0xEF && evm.chainRules.IsLondon {
err = ErrInvalidCode
// Arbitrum: We do not reject Stylus programs and instead store them in the DB
// alongside normal EVM bytecode.
if evm.chainRules.IsArbitrum && IsStylusProgram(ret) {
err = nil
}
}

// if the contract creation ran successfully and no errors were returned
Expand Down
33 changes: 33 additions & 0 deletions core/vm/evm_arbitrum.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,27 @@
package vm

import (
"errors"
"math/big"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)

var (
// Defines prefix bytes for Stylus WASM program bytecode
// when deployed on-chain via a user-initiated transaction.
// These byte prefixes are meant to conflict with the L1 contract EOF
// validation rules so they can be sufficiently differentiated from EVM bytecode.
// This allows us to store WASM programs as code in the stateDB side-by-side
// with EVM contracts, but match against these prefix bytes when loading code
// to execute the WASMs through Stylus rather than the EVM.
stylusEOFMagic = byte(0xEF)
stylusEOFMagicSuffix = byte(0x00)
stylusEOFVersion = byte(0x00)
stylusEOFSectionHeader = byte(0x00)
)

// Depth returns the current depth
func (evm *EVM) Depth() int {
return evm.depth
Expand Down Expand Up @@ -93,3 +108,21 @@ func (p DefaultTxProcessor) GasPriceOp(evm *EVM) *big.Int {
}

func (p DefaultTxProcessor) FillReceiptInfo(*types.Receipt) {}

// IsStylusProgram checks if a specified bytecode is a user-submitted WASM program.
// Stylus differentiates WASMs from EVM bytecode via the prefix 0xEF000000 which will safely fail
// to pass through EVM-bytecode EOF validation rules.
func IsStylusProgram(b []byte) bool {
if len(b) < 4 {
return false
}
return b[0] == stylusEOFMagic && b[1] == stylusEOFMagicSuffix && b[2] == stylusEOFVersion && b[3] == stylusEOFSectionHeader
}

// StripStylusPrefix if the specified input is a stylus program.
func StripStylusPrefix(b []byte) ([]byte, error) {
if !IsStylusProgram(b) {
return nil, errors.New("specified bytecode is not a Stylus program")
}
return b[4:], nil
}

0 comments on commit c4fc7d6

Please sign in to comment.