mipsevm

package
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 16, 2023 License: MIT Imports: 27 Imported by: 0

README

mipsevm

Supported 55 instructions:

'addi', 'addiu', 'addu', 'and', 'andi',
'b', 'beq', 'beqz', 'bgez', 'bgtz', 'blez', 'bltz', 'bne', 'bnez',
'clz', 'divu',
'j', 'jal', 'jalr', 'jr',
'lb', 'lbu', 'lui', 'lw', 'lwr',
'mfhi', 'mflo', 'move', 'movn', 'movz', 'mtlo', 'mul', 'multu',
'negu', 'nop', 'not', 'or', 'ori',
'sb', 'sll', 'sllv', 'slt', 'slti', 'sltiu', 'sltu', 'sra', 'srl', 'srlv', 'subu', 'sw', 'swr', 'sync', 'syscall',
'xor', 'xori'

To run:

  1. Load a program into a state, e.g. using LoadELF.
  2. Patch the program if necessary: e.g. using PatchGo for Go programs, PatchStack for empty initial stack, etc.
  3. Implement the PreimageOracle interface
  4. Instrument the emulator with the state, and pre-image oracle, using NewInstrumentedState
  5. Step through the instrumented state with Step(proof), where proof==true if witness data should be generated. Steps are faster with proof==false.
  6. Optionally repeat the step on-chain by calling MIPS.sol and Oracle.sol, using the above witness data.

Documentation

Index

Constants

View Source
const (
	MipsEBADF  = 0x9
	MipsEINVAL = 0x16
)
View Source
const (
	PageAddrSize = 12
	PageKeySize  = 32 - PageAddrSize
	PageSize     = 1 << PageAddrSize
	PageAddrMask = PageSize - 1
	MaxPageCount = 1 << PageKeySize
	PageKeyMask  = MaxPageCount - 1
)

Note: 2**12 = 4 KiB, the minimum page-size in Unicorn for mmap as well as the Go runtime min phys page size.

Variables

View Source
var (
	StepBytes4                      = crypto.Keccak256([]byte("Step(bytes,bytes)"))[:4]
	CheatBytes4                     = crypto.Keccak256([]byte("cheat(uint256,bytes32,bytes32,uint256)"))[:4]
	LoadKeccak256PreimagePartBytes4 = crypto.Keccak256([]byte("loadKeccak256PreimagePart(uint256,bytes)"))[:4]
)

Functions

func HashPair

func HashPair(left, right [32]byte) [32]byte

func NewEVMEnv

func NewEVMEnv(contracts *Contracts, addrs *Addresses) (*vm.EVM, *state.StateDB)

func PatchGo

func PatchGo(f *elf.File, st *State) error

func PatchStack

func PatchStack(st *State) error

func SE

func SE(dat uint32, idx uint32) uint32

Types

type Addresses

type Addresses struct {
	MIPS         common.Address
	Oracle       common.Address
	Sender       common.Address
	FeeRecipient common.Address
}

type CachedPage

type CachedPage struct {
	Data *Page
	// intermediate nodes only
	Cache [PageSize / 32][32]byte
	// true if the intermediate node is valid
	Ok [PageSize / 32]bool
}

func (*CachedPage) Invalidate

func (p *CachedPage) Invalidate(pageAddr uint32)

func (*CachedPage) InvalidateFull

func (p *CachedPage) InvalidateFull()

func (*CachedPage) MerkleRoot

func (p *CachedPage) MerkleRoot() [32]byte

func (*CachedPage) MerkleizeSubtree

func (p *CachedPage) MerkleizeSubtree(gindex uint64) [32]byte

type Contract

type Contract struct {
	DeployedBytecode struct {
		Object    hexutil.Bytes `json:"object"`
		SourceMap string        `json:"sourceMap"`
	} `json:"deployedBytecode"`
}

func LoadContract

func LoadContract(name string) (*Contract, error)

func (*Contract) SourceMap

func (c *Contract) SourceMap(sourcePaths []string) (*SourceMap, error)

type Contracts

type Contracts struct {
	MIPS   *Contract
	Oracle *Contract
}

func LoadContracts

func LoadContracts() (*Contracts, error)

type HexU32

type HexU32 uint32

HexU32 to lazy-format integer attributes for logging

func (HexU32) MarshalText

func (v HexU32) MarshalText() ([]byte, error)

func (HexU32) String

func (v HexU32) String() string

type InstrMapping

type InstrMapping struct {
	S int32 // start offset in bytes within source (negative when non-existent!)
	L int32 // length in bytes within source (negative when non-existent!)
	F int32 // file index of source (negative when non-existent!)
	J byte  // jump type (i=into, o=out, -=regular)
	M int32 // modifier depth
}

type InstrumentedState

type InstrumentedState struct {
	// contains filtered or unexported fields
}

func NewInstrumentedState

func NewInstrumentedState(state *State, po PreimageOracle, stdOut, stdErr io.Writer) *InstrumentedState

func (*InstrumentedState) Step

func (m *InstrumentedState) Step(proof bool) (wit *StepWitness, err error)

type LineCol

type LineCol struct {
	Line uint32
	Col  uint32
}

type LoggingWriter

type LoggingWriter struct {
	Name string
	Log  log.Logger
}

LoggingWriter is a simple util to wrap a logger, and expose an io Writer interface, for the program running within the VM to write to.

func (*LoggingWriter) Write

func (lw *LoggingWriter) Write(b []byte) (int, error)

type Memory

type Memory struct {
	// contains filtered or unexported fields
}

func NewMemory

func NewMemory() *Memory

func (*Memory) AllocPage

func (m *Memory) AllocPage(pageIndex uint32) *CachedPage

func (*Memory) ForEachPage

func (m *Memory) ForEachPage(fn func(pageIndex uint32, page *Page) error) error

func (*Memory) GetMemory

func (m *Memory) GetMemory(addr uint32) uint32

func (*Memory) Invalidate

func (m *Memory) Invalidate(addr uint32)

func (*Memory) MarshalJSON

func (m *Memory) MarshalJSON() ([]byte, error)

func (*Memory) MerkleProof

func (m *Memory) MerkleProof(addr uint32) (out [28 * 32]byte)

func (*Memory) MerkleRoot

func (m *Memory) MerkleRoot() [32]byte

func (*Memory) MerkleizeSubtree

func (m *Memory) MerkleizeSubtree(gindex uint64) [32]byte

func (*Memory) PageCount

func (m *Memory) PageCount() int

func (*Memory) ReadMemoryRange

func (m *Memory) ReadMemoryRange(addr uint32, count uint32) io.Reader

func (*Memory) SetMemory

func (m *Memory) SetMemory(addr uint32, v uint32)

func (*Memory) SetMemoryRange

func (m *Memory) SetMemoryRange(addr uint32, r io.Reader) error

func (*Memory) UnmarshalJSON

func (m *Memory) UnmarshalJSON(data []byte) error

func (*Memory) Usage

func (m *Memory) Usage() string

type Metadata

type Metadata struct {
	Symbols []Symbol `json:"symbols"`
}

func MakeMetadata

func MakeMetadata(elfProgram *elf.File) (*Metadata, error)

func (*Metadata) LookupSymbol

func (m *Metadata) LookupSymbol(addr uint32) string

func (*Metadata) SymbolMatcher

func (m *Metadata) SymbolMatcher(name string) func(addr uint32) bool

type Page

type Page [PageSize]byte

func (*Page) MarshalText

func (p *Page) MarshalText() ([]byte, error)

func (*Page) UnmarshalText

func (p *Page) UnmarshalText(dat []byte) error

type PreimageOracle

type PreimageOracle interface {
	Hint(v []byte)
	GetPreimage(k [32]byte) []byte
}

type SourceMap

type SourceMap struct {
	// source names
	Sources []string
	// per source, source offset -> line/col
	PosData [][]LineCol
	// per bytecode byte, byte index -> instr
	Instr []InstrMapping
}

func ParseSourceMap

func ParseSourceMap(sources []string, bytecode []byte, sourceMap string) (*SourceMap, error)

ParseSourceMap parses a solidity sourcemap: mapping bytecode indices to source references. See https://docs.soliditylang.org/en/latest/internals/source_mappings.html

func (*SourceMap) FormattedInfo

func (s *SourceMap) FormattedInfo(pc uint64) string

func (*SourceMap) Info

func (s *SourceMap) Info(pc uint64) (source string, line uint32, col uint32)

type SourceMapTracer

type SourceMapTracer struct {
	// contains filtered or unexported fields
}

func NewSourceMapTracer

func NewSourceMapTracer(srcMaps map[common.Address]*SourceMap, out io.Writer) *SourceMapTracer

func (*SourceMapTracer) CaptureEnd

func (s *SourceMapTracer) CaptureEnd(output []byte, gasUsed uint64, err error)

func (*SourceMapTracer) CaptureEnter

func (s *SourceMapTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int)

func (*SourceMapTracer) CaptureExit

func (s *SourceMapTracer) CaptureExit(output []byte, gasUsed uint64, err error)

func (*SourceMapTracer) CaptureFault

func (s *SourceMapTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error)

func (*SourceMapTracer) CaptureStart

func (s *SourceMapTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int)

func (*SourceMapTracer) CaptureState

func (s *SourceMapTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error)

func (*SourceMapTracer) CaptureTxEnd

func (s *SourceMapTracer) CaptureTxEnd(restGas uint64)

func (*SourceMapTracer) CaptureTxStart

func (s *SourceMapTracer) CaptureTxStart(gasLimit uint64)

type State

type State struct {
	Memory *Memory `json:"memory"`

	PreimageKey    common.Hash `json:"preimageKey"`
	PreimageOffset uint32      `json:"preimageOffset"` // note that the offset includes the 8-byte length prefix

	PC     uint32 `json:"pc"`
	NextPC uint32 `json:"nextPC"`
	LO     uint32 `json:"lo"`
	HI     uint32 `json:"hi"`
	Heap   uint32 `json:"heap"` // to handle mmap growth

	ExitCode uint8 `json:"exit"`
	Exited   bool  `json:"exited"`

	Step uint64 `json:"step"`

	Registers [32]uint32 `json:"registers"`

	// LastHint is optional metadata, and not part of the VM state itself.
	// It is used to remember the last pre-image hint,
	// so a VM can start from any state without fetching prior pre-images,
	// and instead just repeat the last hint on setup,
	// to make sure pre-image requests can be served.
	// The first 4 bytes are a uin32 length prefix.
	// Warning: the hint MAY NOT BE COMPLETE. I.e. this is buffered,
	// and should only be read when len(LastHint) > 4 && uint32(LastHint[:4]) >= len(LastHint[4:])
	LastHint hexutil.Bytes `json:"lastHint,omitempty"`
}

func LoadELF

func LoadELF(f *elf.File) (*State, error)

func (*State) EncodeWitness

func (s *State) EncodeWitness() []byte

type StepWitness

type StepWitness struct {
	// encoded state witness
	State []byte

	MemProof []byte

	PreimageKey    [32]byte // zeroed when no pre-image is accessed
	PreimageValue  []byte   // including the 8-byte length prefix
	PreimageOffset uint32
}

func (*StepWitness) EncodePreimageOracleInput

func (wit *StepWitness) EncodePreimageOracleInput() ([]byte, error)

func (*StepWitness) EncodeStepInput

func (wit *StepWitness) EncodeStepInput() []byte

func (*StepWitness) HasPreimage

func (wit *StepWitness) HasPreimage() bool

type Symbol

type Symbol struct {
	Name  string `json:"name"`
	Start uint32 `json:"start"`
	Size  uint32 `json:"size"`
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL