compiler

package
v0.0.0-...-866bf41 Latest Latest
Warning

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

Go to latest
Published: Sep 26, 2018 License: LGPL-3.0 Imports: 25 Imported by: 0

README

NEO-GO smart contract compiler

The neo-go compiler compiles Go programs to bytecode that the NEO virtual machine can understand.

Currently supported

Go internals
  • type checking
  • multiple assignments
  • global variables
  • types int, string, byte and booleans
  • struct types + method receives
  • functions
  • composite literals []int, []string, []byte
  • basic if statements
  • binary expressions
  • return statements
  • for loops
  • imports
Go builtins
  • len
  • append
VM API (interop layer)
  • storage
  • runtime
VM utility helper functions
  • SHA1
  • SHA256
  • Hash256
  • Hash160

Not yet implemented

  • range
  • some parts of the interop layer (VM API)

Not supported

Due to the limitations of the NEO virtual machine, features listed below will not be supported.

  • channels
  • goroutines
  • multiple returns

Quick start

Compile a smart contract
./bin/neo-go contract compile -i mycontract.go

By default the filename will be the name of your .go file with the .avm extension, the file will be located in the same directory where your Go contract is. If you want another location for your compiled contract:

./bin/neo-go contract compile -i mycontract.go --out /Users/foo/bar/contract.avm
Debugging your smart contract

You can dump the opcodes generated by the compiler with the following command:

./bin/neo-go contract opdump -i mycontract.go

This will result in something like this:

INDEX    OPCODE    DESC
0        0x52      OpPush2
1        0xc5      OpNewArray
2        0x6b      OpToAltStack
3        0x 0      OpPush0
4        0x6c      OpFromAltStack
5        0x76      OpDup
6        0x6b      OpToAltStack
7        0x 0      OpPush0
8        0x52      OpPush2
9        0x7a      OpRoll
10       0xc4      OpSetItem
Test invoke a compiled contract

You can simulate a test invocation of your compiled contract by the VM, to know the total gas cost for example, with the following command:

./bin/neo-go contract testinvoke -i mycompiledcontract.avm

Will output something like:

{
  "state": "HALT, BREAK",
  "gas_consumed": "0.006",
  "Stack": [
    {
      "type": "Integer",
      "value": "9"
    }
  ]
}

Smart contract examples

Check if the invoker of the contract is the owning address
package mycontract

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

var owner = []byte{0xaf, 0x12, 0xa8, 0x68, 0x7b, 0x14, 0x94, 0x8b, 0xc4, 0xa0, 0x08, 0x12, 0x8a, 0x55, 0x0a, 0x63, 0x69, 0x5b, 0xc1, 0xa5}

func Main() bool {
    isOwner := runtime.CheckWitness(owner)

    if isOwner {
        runtime.Log("invoker is the owner")
        return true
    }

    return false
}
Simple token
package mytoken

import (
	"github.com/CityOfZion/neo-go/pkg/vm/api/runtime"
	"github.com/CityOfZion/neo-go/pkg/vm/api/storage"
)

var owner = []byte{0xaf, 0x12, 0xa8, 0x68, 0x7b, 0x14, 0x94, 0x8b, 0xc4, 0xa0, 0x08, 0x12, 0x8a, 0x55, 0x0a, 0x63, 0x69, 0x5b, 0xc1, 0xa5}

type Token struct {
	Name        string
	Symbol      string
	TotalSupply int
	Owner       []byte
}

func (t Token) AddToCirculation(amount int) bool {
	ctx := storage.Context()
	inCirc := storage.GetInt(ctx, "in_circ")
	inCirc += amount
	storage.Put(ctx, "in_circ", inCirc)
	return true
}

func newToken() Token {
	return Token{
		Name:        "your awesome NEO token",
		Symbol:      "YANT",
		TotalSupply: 1000,
		Owner:       owner,
	}
}

func Main(operation string, args []interface{}) bool {
	token := newToken()
	trigger := runtime.GetTrigger()

	if trigger == runtime.Verification() {
		isOwner := runtime.CheckWitness(token.Owner)
		if isOwner {
			return true
		}
		return false
	}

	if trigger == runtime.Application() {
		if operation == "mintTokens" {
			token.AddToCirculation(100)
		}
	}

	return true
}

How to report compiler bugs

  1. Make a proper testcase (example testcases can be found in the tests folder)
  2. Create an issue on Github
  3. Make a PR with a reference to the created issue, containing the testcase that proves the bug
  4. Either you fix the bug yourself or wait for patch that solves the problem

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CodeGen

func CodeGen(info *buildInfo, genabi bool) (*bytes.Buffer, *bytes.Buffer, error)

CodeGen is the function that compiles the program to bytecode.

func Compile

func Compile(r io.Reader, o *Options) ([]byte, []byte, error)

Compile compiles a Go program into bytecode that can run on the NEO virtual machine.

func CompileAndSave

func CompileAndSave(src string, o *Options) error

CompileAndSave will compile and save the file to disk.

func DumpOpcode

func DumpOpcode(src string) error

DumpOpcode compiles the program and dumps the opcode in a user friendly format.

Types

type Function

type Function struct {
	Name       string      `json:"name"`
	Parameters []Paramster `json:"parameters"`
	Returntype string      `json:"returntype"`
}

type Functions

type Functions struct {
	Functions []Function `json:"functions"`
}

func MakeAbi

func MakeAbi(main *ast.FuncDecl) Functions

type Options

type Options struct {
	// The extension of the output file default set to .avm
	Ext string

	// The name of the output file.
	Outfile string

	// Debug will output an hex encoded string of the generated bytecode.
	Debug bool

	// generate abi file
	AbiGen bool
}

Options contains all the parameters that affect the behaviour of the compiler.

type Paramster

type Paramster struct {
	PName string `json:"name"`
	PType string `json:"type"`
}

Jump to

Keyboard shortcuts

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