neo-go/pkg/vm/compiler
Anthony De Meulemeester 1a1a19da7d
Smartcontract (#39)
* deleted transfer_output added asset type and transaction result to core

* removed writing 0x00 when buffer length is 0

* Refactored emit into VM package + moved tx to own package.

* implemented transaction along with claimTransaction.

* refactored naming of transaction + added decode address for uint160 types

* removed unnecessary folder and files.

* transaction/smartcontract logic

* bumped version 0.24.0
2018-03-04 14:56:49 +01:00
..
tests Compiler (#37) 2018-03-02 16:49:10 +01:00
analysis.go Compiler update (basic sc ready) (#31) 2018-02-27 10:04:24 +01:00
codegen.go Compiler update (basic sc ready) (#31) 2018-02-27 10:04:24 +01:00
compiler.go Compiler update (basic sc ready) (#31) 2018-02-27 10:04:24 +01:00
emit.go Smartcontract (#39) 2018-03-04 14:56:49 +01:00
func_scope.go Compiler update (basic sc ready) (#31) 2018-02-27 10:04:24 +01:00
README.md Compiler (#37) 2018-03-02 16:49:10 +01:00

NEO-GO Compiler

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

NOTE: The neo-go compiler is under very active development and will be updated on a weekly basis. The API is likely going to change, hence do not use this in production environments (mainnet) yet.

For help, questions and discussion feel free to join the City Of Zion discord and hop in the #golang channel. Or reach out to me on twitter @anthdm

Currently supported

Go internals

  • type checker
  • multiple assigns
  • 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
  • imports

VM API (interop layer)

  • storage
  • runtime

Not yet implemented

  • for loops
  • ranges
  • builtins (append, len, ..)
  • 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

Smart contract examples

Check if the invoker of the contract is the owning address

package mycontract

import "github.com/CityOfZion/neo-go/pkg/vm/smartcontract/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/smartcontract/runtime"
	"github.com/CityOfZion/neo-go/pkg/vm/smartcontract/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.GetContext()
	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

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 you called the command from. 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