vm

package
v0.5.0-pre Latest Latest
Warning

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

Go to latest
Published: Aug 26, 2019 License: MIT Imports: 18 Imported by: 0

README

NEO-GO-VM

A cross platform virtual machine implementation for avm compatible programs.

Installation

With neo-go

Install dependencies.

neo-go uses dep as its dependency manager. After installing deps you can run:

make deps

Build the neo-go cli:

make build

Start the virtual machine:

./bin/neo-go vm
    _   ____________        __________      _    ____  ___
   / | / / ____/ __ \      / ____/ __ \    | |  / /  |/  /
  /  |/ / __/ / / / /_____/ / __/ / / /____| | / / /|_/ /
 / /|  / /___/ /_/ /_____/ /_/ / /_/ /_____/ |/ / /  / /
/_/ |_/_____/\____/      \____/\____/      |___/_/  /_/


NEO-GO-VM >

Standalone

More information about standalone installation coming soon.

Usage

    _   ____________        __________      _    ____  ___
   / | / / ____/ __ \      / ____/ __ \    | |  / /  |/  /
  /  |/ / __/ / / / /_____/ / __/ / / /____| | / / /|_/ /
 / /|  / /___/ /_/ /_____/ /_/ / /_/ /_____/ |/ / /  / /
/_/ |_/_____/\____/      \____/\____/      |___/_/  /_/


NEO-GO-VM > help

COMMAND    USAGE
astack     show alt stack details
break      place a breakpoint (> break 1)
cont       continue execution of the current loaded script
estack     show evaluation stack details
exit       exit the VM prompt
help       show available commands
ip         show the current instruction
istack     show invocation stack details
loadavm    load an avm script into the VM (> load /path/to/script.avm)
loadgo     compile and load a .go file into the VM (> load /path/to/file.go)
loadhex    load a hex string into the VM (> loadhex 006166 )
ops        show the opcodes of the current loaded program
run        execute the current loaded script
step       step (n) instruction in the program (> step 10)
Loading in your script

To load an avm script into the VM:

NEO-GO-VM > loadavm ../contract.avm
READY: loaded 36 instructions

Run the script:

NEO-GO-VM > run
[
    {
        "value": 1,
        "type": "BigInteger"
    }
]

You can also directly compile and load .go files:

NEO-GO-VM > loadgo ../contract.go
READY: loaded 36 instructions

To make it even more complete, you can directly load hex strings into the VM:

NEO-GO-VM > loadhex 54c56b006c766b00527ac46c766b00c391640b006203005a616c756662030000616c7566
READY: loaded 36 instructions
NEO-GO-VM > run
[
    {
        "value": 10,
        "type": "BigInteger"
    }
]

Running programs with arguments

You can invoke smart contracts with arguments. Take the following roll the dice smartcontract as example.

package rollthedice

import "github.com/CityOfZion/neo-go/pkg/interop/runtime"

func Main(method string, args []interface{}) int {
    if method == "rollDice" {
        // args parameter is always of type []interface, hence we need to 
        // cast it to an int.
        rollDice(args[0].(int))
    }
    return 0
}

func rollDice(number int) {
    if number == 0 {
        runtime.Log("you rolled 0, better luck next time!")
    }
    if number == 1 {
        runtime.Log("you rolled 1, still better then 0!")
    }
    if number == 2 {
        runtime.Log("you rolled 2, coming closer..") 
    }
    if number == 3 {
        runtime.Log("Sweet you rolled 3. This dice has only 3 sides o_O")
    }
}

To invoke this contract we need to specify both the method and the arguments.

The first parameter (called method or operation) is always of type string. Notice that arguments can have different types, to make the VM aware of the type we need to specify it when calling run:

NEO-GO-VM > run rollDice int:1

The method is always of type string, hence we don't need to specify the type.

To add more then 1 argument:

NEO-GO-VM > run someMethod int:1 int:2 string:foo string:bar

Current supported types:

  • int (int:1 int:100)
  • string (string:foo string:this is a string)
Debugging

The neo-go-vm provides a debugger to inspect your program in-depth.

Step 4 instructions.

NEO-GO-VM > step 4
at breakpoint 4 (Opush4)
NEO-GO-VM 4 >

Using just step will execute 1 instruction at a time.

NEO-GO-VM > step
instruction pointer at 5 (Odup)
NEO-GO-VM 5 >

To place breakpoints:

NEO-GO-VM > break 10
breakpoint added at instruction 10
NEO-GO-VM > cont
at breakpoint 10 (Osetitem)
NEO-GO-VM 10 > cont

Inspecting the evaluation stack:

NEO-GO-VM > estack
[
    {
        "value": [
            null,
            null,
            null,
            null,
            null,
            null,
            null
        ],
        "type": "Array"
    },
    {
        "value": 4,
        "type": "BigInteger"
    }
]

There are more stacks that you can inspect.

  • astack alt stack
  • istack invocation stack

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Emit

func Emit(w *bytes.Buffer, op Instruction, b []byte) error

Emit a VM Instruction with data to the given buffer.

func EmitAppCall

func EmitAppCall(w *bytes.Buffer, scriptHash util.Uint160, tailCall bool) error

EmitAppCall emits an appcall, if tailCall is true, tailCall opcode will be emitted instead.

func EmitAppCallWithOperation

func EmitAppCallWithOperation(w *bytes.Buffer, scriptHash util.Uint160, operation string) error

EmitAppCallWithOperation emits an appcall with the given operation.

func EmitAppCallWithOperationAndData

func EmitAppCallWithOperationAndData(w *bytes.Buffer, scriptHash util.Uint160, operation string, data []byte) error

EmitAppCallWithOperationAndData emits an appcall with the given operation and data.

func EmitBool

func EmitBool(w io.ByteWriter, ok bool) error

EmitBool emits a bool type the given buffer.

func EmitBytes

func EmitBytes(w *bytes.Buffer, b []byte) error

EmitBytes emits a byte array to the given buffer.

func EmitCall

func EmitCall(w *bytes.Buffer, op Instruction, label int16) error

EmitCall emits a call Instruction with label to the given buffer.

func EmitInt

func EmitInt(w *bytes.Buffer, i int64) error

EmitInt emits a int type to the given buffer.

func EmitJmp

func EmitJmp(w *bytes.Buffer, op Instruction, label int16) error

EmitJmp emits a jump Instruction along with label to the given buffer.

func EmitOpcode

func EmitOpcode(w io.ByteWriter, op Instruction) error

EmitOpcode emits a single VM Instruction the given buffer.

func EmitString

func EmitString(w *bytes.Buffer, s string) error

EmitString emits a string to the given buffer.

func EmitSyscall

func EmitSyscall(w *bytes.Buffer, api string) error

EmitSyscall emits the syscall API to the given buffer. Syscall API string cannot be 0.

Types

type ArrayItem

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

ArrayItem represents a new ArrayItem object.

func NewArrayItem

func NewArrayItem(items []StackItem) *ArrayItem

NewArrayItem returns a new ArrayItem object.

func (*ArrayItem) MarshalJSON

func (i *ArrayItem) MarshalJSON() ([]byte, error)

MarshalJSON implements the json.Marshaler interface.

func (*ArrayItem) String

func (i *ArrayItem) String() string

func (*ArrayItem) Value

func (i *ArrayItem) Value() interface{}

Value implements StackItem interface.

type BigIntegerItem

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

BigIntegerItem represents a big integer on the stack.

func NewBigIntegerItem

func NewBigIntegerItem(value int) *BigIntegerItem

NewBigIntegerItem returns an new BigIntegerItem object.

func (*BigIntegerItem) MarshalJSON

func (i *BigIntegerItem) MarshalJSON() ([]byte, error)

MarshalJSON implements the json.Marshaler interface.

func (*BigIntegerItem) String

func (i *BigIntegerItem) String() string

func (*BigIntegerItem) Value

func (i *BigIntegerItem) Value() interface{}

Value implements StackItem interface.

type BoolItem

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

func NewBoolItem

func NewBoolItem(val bool) *BoolItem

NewBoolItem returns an new BoolItem object.

func (*BoolItem) MarshalJSON

func (i *BoolItem) MarshalJSON() ([]byte, error)

MarshalJSON implements the json.Marshaler interface.

func (*BoolItem) String

func (i *BoolItem) String() string

func (*BoolItem) Value

func (i *BoolItem) Value() interface{}

Value implements StackItem interface.

type ByteArrayItem

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

ByteArrayItem represents a byte array on the stack.

func NewByteArrayItem

func NewByteArrayItem(b []byte) *ByteArrayItem

NewByteArrayItem returns an new ByteArrayItem object.

func (*ByteArrayItem) MarshalJSON

func (i *ByteArrayItem) MarshalJSON() ([]byte, error)

MarshalJSON implements the json.Marshaler interface.

func (*ByteArrayItem) String

func (i *ByteArrayItem) String() string

func (*ByteArrayItem) Value

func (i *ByteArrayItem) Value() interface{}

Value implements StackItem interface.

type Context

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

Context represent the current execution context of the VM.

func NewContext

func NewContext(b []byte) *Context

NewContext return a new Context object.

func (*Context) Copy

func (c *Context) Copy() *Context

Copy returns an new exact copy of c.

func (*Context) CurrInstr

func (c *Context) CurrInstr() (int, Instruction)

CurrInstr returns the current instruction and opcode.

func (*Context) IP

func (c *Context) IP() int

IP returns the absolute instruction without taking 0 into account. If that program starts the ip = 0 but IP() will return 1, cause its the first instruction.

func (*Context) LenInstr

func (c *Context) LenInstr() int

LenInstr returns the number of instructions loaded.

func (*Context) Next

func (c *Context) Next() Instruction

Next return the next instruction to execute.

func (*Context) Program

func (c *Context) Program() []byte

Program returns the loaded program.

func (*Context) String

func (c *Context) String() string

func (*Context) Value

func (c *Context) Value() interface{}

Value implements StackItem interface.

type Element

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

Element represents an element in the double linked list (the stack), which will hold the underlying StackItem.

func NewElement

func NewElement(v interface{}) *Element

NewElement returns a new Element object, with its underlying value inferred to the corresponding type.

func (*Element) BigInt

func (e *Element) BigInt() *big.Int

BigInt attempts to get the underlying value of the element as a big integer. Will panic if the assertion failed which will be caught by the VM.

func (*Element) Bool

func (e *Element) Bool() bool

Bool attempts to get the underlying value of the element as a boolean. Will panic if the assertion failed which will be caught by the VM.

func (*Element) Bytes

func (e *Element) Bytes() []byte

Bytes attempts to get the underlying value of the element as a byte array. Will panic if the assertion failed which will be caught by the VM.

func (*Element) Next

func (e *Element) Next() *Element

Next returns the next element in the stack.

func (*Element) Prev

func (e *Element) Prev() *Element

Prev returns the previous element in the stack.

type Instruction

type Instruction byte

Instruction represents an single operation for the NEO virtual machine.

const (
	// Constants
	PUSH0       Instruction = 0x00
	PUSHF       Instruction = PUSH0
	PUSHBYTES1  Instruction = 0x01
	PUSHBYTES75 Instruction = 0x4B
	PUSHDATA1   Instruction = 0x4C
	PUSHDATA2   Instruction = 0x4D
	PUSHDATA4   Instruction = 0x4E
	PUSHM1      Instruction = 0x4F
	PUSH1       Instruction = 0x51
	PUSHT       Instruction = PUSH1
	PUSH2       Instruction = 0x52
	PUSH3       Instruction = 0x53
	PUSH4       Instruction = 0x54
	PUSH5       Instruction = 0x55
	PUSH6       Instruction = 0x56
	PUSH7       Instruction = 0x57
	PUSH8       Instruction = 0x58
	PUSH9       Instruction = 0x59
	PUSH10      Instruction = 0x5A
	PUSH11      Instruction = 0x5B
	PUSH12      Instruction = 0x5C
	PUSH13      Instruction = 0x5D
	PUSH14      Instruction = 0x5E
	PUSH15      Instruction = 0x5F
	PUSH16      Instruction = 0x60

	// Flow control
	NOP      Instruction = 0x61
	JMP      Instruction = 0x62
	JMPIF    Instruction = 0x63
	JMPIFNOT Instruction = 0x64
	CALL     Instruction = 0x65
	RET      Instruction = 0x66
	APPCALL  Instruction = 0x67
	SYSCALL  Instruction = 0x68
	TAILCALL Instruction = 0x69

	// Stack
	DUPFROMALTSTACK Instruction = 0x6A
	TOALTSTACK      Instruction = 0x6B
	FROMALTSTACK    Instruction = 0x6C
	XDROP           Instruction = 0x6D
	XSWAP           Instruction = 0x72
	XTUCK           Instruction = 0x73
	DEPTH           Instruction = 0x74
	DROP            Instruction = 0x75
	DUP             Instruction = 0x76
	NIP             Instruction = 0x77
	OVER            Instruction = 0x78
	PICK            Instruction = 0x79
	ROLL            Instruction = 0x7A
	ROT             Instruction = 0x7B
	SWAP            Instruction = 0x7C
	TUCK            Instruction = 0x7D

	// Splice
	CAT    Instruction = 0x7E
	SUBSTR Instruction = 0x7F
	LEFT   Instruction = 0x80
	RIGHT  Instruction = 0x81
	SIZE   Instruction = 0x82

	// Bitwise logic
	INVERT Instruction = 0x83
	AND    Instruction = 0x84
	OR     Instruction = 0x85
	XOR    Instruction = 0x86
	EQUAL  Instruction = 0x87

	// Arithmetic
	INC         Instruction = 0x8B
	DEC         Instruction = 0x8C
	SIGN        Instruction = 0x8D
	NEGATE      Instruction = 0x8F
	ABS         Instruction = 0x90
	NOT         Instruction = 0x91
	NZ          Instruction = 0x92
	ADD         Instruction = 0x93
	SUB         Instruction = 0x94
	MUL         Instruction = 0x95
	DIV         Instruction = 0x96
	MOD         Instruction = 0x97
	SHL         Instruction = 0x98
	SHR         Instruction = 0x99
	BOOLAND     Instruction = 0x9A
	BOOLOR      Instruction = 0x9B
	NUMEQUAL    Instruction = 0x9C
	NUMNOTEQUAL Instruction = 0x9E
	LT          Instruction = 0x9F
	GT          Instruction = 0xA0
	LTE         Instruction = 0xA1
	GTE         Instruction = 0xA2
	MIN         Instruction = 0xA3
	MAX         Instruction = 0xA4
	WITHIN      Instruction = 0xA5

	// Crypto
	SHA1          Instruction = 0xA7
	SHA256        Instruction = 0xA8
	HASH160       Instruction = 0xA9
	HASH256       Instruction = 0xAA
	CHECKSIG      Instruction = 0xAC
	CHECKMULTISIG Instruction = 0xAE

	// Array
	ARRAYSIZE Instruction = 0xC0
	PACK      Instruction = 0xC1
	UNPACK    Instruction = 0xC2
	PICKITEM  Instruction = 0xC3
	SETITEM   Instruction = 0xC4
	NEWARRAY  Instruction = 0xC5
	NEWSTRUCT Instruction = 0xC6
	APPEND    Instruction = 0xC8
	REVERSE   Instruction = 0xC9
	REMOVE    Instruction = 0xCA

	// Exceptions
	THROW      Instruction = 0xF0
	THROWIFNOT Instruction = 0xF1
)

Viable list of supported instruction constants.

func (Instruction) String

func (i Instruction) String() string

type InteropFunc

type InteropFunc func(vm *VM) error

InteropFunc allows to hook into the VM.

type Mode

type Mode uint

Mode configures behaviour of the VM.

var (
	ModeMute Mode = 1 << 0
)

Available VM Modes.

type Stack

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

Stack represents a Stack backed by a double linked list.

func NewStack

func NewStack(n string) *Stack

NewStack returns a new stack name by the given name.

func (*Stack) Back

func (s *Stack) Back() *Element

Back returns the element at the end of the stack. Nil if the stack is empty.

func (*Stack) Clear

func (s *Stack) Clear()

Clear will clear all elements on the stack and set its length to 0.

func (*Stack) Dup

func (s *Stack) Dup(n int) *Element

Dup will duplicate and return the element at position n. Dup is used for copying elements on to the top of its own stack.

s.Push(s.Peek(0)) // will result in unexpected behaviour.
s.Push(s.Dup(0)) // is the correct approach.

func (*Stack) InsertAt

func (s *Stack) InsertAt(e *Element, n int) *Element

InsertAt will insert the given item (n) deep on the stack.

func (*Stack) InsertBefore

func (s *Stack) InsertBefore(e, mark *Element) *Element

InsertBefore will insert the element before the mark on the stack.

func (*Stack) Iter

func (s *Stack) Iter(f func(*Element))

Iter will iterate over all the elements int the stack, starting from the top of the stack.

s.Iter(func(elem *Element) {
	// do something with the element.
})

func (*Stack) Len

func (s *Stack) Len() int

Len return the number of elements that are on the stack.

func (*Stack) Peek

func (s *Stack) Peek(n int) *Element

Peek returns the element (n) far in the stack beginning from the top of the stack.

n = 0 => will return the element on top of the stack.

func (*Stack) Pop

func (s *Stack) Pop() *Element

Pop removes and returns the element on top of the stack.

func (*Stack) Push

func (s *Stack) Push(e *Element)

Push pushes the given element on the stack.

func (*Stack) PushVal

func (s *Stack) PushVal(v interface{})

PushVal will push the given value on the stack. It will infer the underlying StackItem to its corresponding type.

func (*Stack) Remove

func (s *Stack) Remove(e *Element) *Element

Remove removes and returns the given element from the stack.

func (*Stack) RemoveAt

func (s *Stack) RemoveAt(n int) *Element

RemoveAt removes the element (n) deep on the stack beginning from the top of the stack.

func (*Stack) Top

func (s *Stack) Top() *Element

Top returns the element on top of the stack. Nil if the stack is empty.

type StackItem

type StackItem interface {
	fmt.Stringer
	Value() interface{}
}

A StackItem represents the "real" value that is pushed on the stack.

type State

type State uint8

State of the VM.

func StateFromString

func StateFromString(s string) (st State, err error)

func (State) HasFlag

func (s State) HasFlag(f State) bool

func (State) MarshalJSON

func (s State) MarshalJSON() (data []byte, err error)

func (State) String

func (s State) String() string

func (*State) UnmarshalJSON

func (s *State) UnmarshalJSON(data []byte) (err error)

type StructItem

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

StructItem represents a struct on the stack.

func NewStructItem

func NewStructItem(items []StackItem) *StructItem

NewStructItem returns an new StructItem object.

func (*StructItem) String

func (i *StructItem) String() string

func (*StructItem) Value

func (i *StructItem) Value() interface{}

Value implements StackItem interface.

type VM

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

VM represents the virtual machine.

func New

func New(mode Mode) *VM

New returns a new VM object ready to load .avm bytecode scripts.

func (*VM) AddBreakPoint

func (v *VM) AddBreakPoint(n int)

AddBreakPoint adds a breakpoint to the current context.

func (*VM) AddBreakPointRel

func (v *VM) AddBreakPointRel(n int)

AddBreakPointRel adds a breakpoint relative to the current instruction pointer.

func (*VM) Astack

func (v *VM) Astack() *Stack

Astack will return the alt stack so interop hooks can utilize this.

func (*VM) Context

func (v *VM) Context() *Context

Context returns the current executed context. Nil if there is no context, which implies no program is loaded.

func (*VM) Estack

func (v *VM) Estack() *Stack

Estack will return the evaluation stack so interop hooks can utilize this.

func (*VM) Istack

func (v *VM) Istack() *Stack

Istack will return the invocation stack so interop hooks can utilize this.

func (*VM) Load

func (v *VM) Load(prog []byte)

func (*VM) LoadArgs

func (v *VM) LoadArgs(method []byte, args []StackItem)

LoadArgs will load in the arguments used in the Mian entry point.

func (*VM) LoadFile

func (v *VM) LoadFile(path string) error

LoadFile will load a program from the given path, ready to execute it.

func (*VM) LoadScript

func (v *VM) LoadScript(b []byte)

LoadScript will load a script from the internal script table. It will immediately push a new context created from this script to the invocation stack and starts executing it.

func (*VM) PopResult

func (v *VM) PopResult() interface{}

PopResult is used to pop the first item of the evaluation stack. This allows us to test compiler and vm in a bi-directional way.

func (*VM) PrintOps

func (v *VM) PrintOps()

PrintOps will print the opcodes of the current loaded program to stdout.

func (*VM) Ready

func (v *VM) Ready() bool

Ready return true if the VM ready to execute the loaded program. Will return false if no program is loaded.

func (*VM) RegisterInteropFunc

func (v *VM) RegisterInteropFunc(name string, f InteropFunc)

RegisterInteropFunc will register the given InteropFunc to the VM.

func (*VM) Run

func (v *VM) Run()

Run starts the execution of the loaded program.

func (*VM) Stack

func (v *VM) Stack(n string) string

Stack returns json formatted representation of the given stack.

func (*VM) Step

func (v *VM) Step()

Step 1 instruction in the program.

Directories

Path Synopsis
tests
bar
foo

Jump to

Keyboard shortcuts

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