From f8093e415ecb8258fbf75589f6255a94e357a89c Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Tue, 19 May 2020 00:17:05 +0300 Subject: [PATCH] docs: update compiler.md, bring it up to date And add one more reference to it into the main README. --- README.md | 11 ++- docs/compiler.md | 249 ++++++++++++++++++++++++++++------------------- 2 files changed, 160 insertions(+), 100 deletions(-) diff --git a/README.md b/README.md index 1998111ea..0b775f1b4 100644 --- a/README.md +++ b/README.md @@ -92,7 +92,16 @@ Available network flags: - `--privnet, -p` - `--testnet, -t` -#Developer notes +## Smart contract development + +Please refer to [neo-go smart contract development +workshop](https://github.com/nspcc-dev/neo-go-sc-wrkshp) that shows some +simple contracts that can be compiled/deployed/run using neo-go compiler, SDK +and private network. For details on how Go code is translated to Neo VM +bytecode and what you can and can not do in smart contract please refer to the +[compiler documentation](docs/compiler.md). + +# Developer notes Nodes have such features as [Prometheus](https://prometheus.io/docs/guides/go-application) and [Pprof](https://golang.org/pkg/net/http/pprof/) in order to have additional information about them for debugging. diff --git a/docs/compiler.md b/docs/compiler.md index a7e59652c..bd45239ef 100644 --- a/docs/compiler.md +++ b/docs/compiler.md @@ -2,66 +2,36 @@ The neo-go compiler compiles Go programs to bytecode that the NEO virtual machine can understand. -## Currently supported +## Language compatibility -### 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 +The compiler is mostly compatible with regular Go language specification, but +there are some important deviations that you need to be aware of that make it +a dialect of Go rather than a complete port of the language: + * `make()` ane `new()` are not supported, most of the time you can substitute + them with composite literals + * there is no real distinction between different integer types, all of them + work as big.Int in Go with a limit of 256 bit in width, so you can use + `int` for just about anything. This is the way integers work in Neo VM and + adding proper Go types emulation is considered to be too costly. + * goroutines, channels and garbage collection are not supported and will + never be because emulating that aspects of Go runtime on top of Neo VM is + close to impossible + * even though `panic()` is supported, `recover()` is not, `panic` shuts the + VM down + * lambdas are not supported (#939) + * it's not possible to rename imported interop packages, they won't work this + way (#397, #913) -### Go builtins -- len -- append - -### VM API (interop layer) +## VM API (interop layer) Compiler translates interop function calls into NEO VM syscalls or (for custom -functions) into NEO VM instructions. [Refer to GoDoc](https://godoc.org/github.com/nspcc-dev/neo-go/pkg/interop) for full API documentation. - -#### Standard NEO Smart Contract API -- account -- asset -- attribute -- block -- blockchain -- contract -- engine -- header -- input -- iterator -- output -- runtime -- storage -- transaction - -#### Custom VM utility helper functions -- crypto: - - `SHA1` - - `SHA256` - - `Hash256` - - `Hash160` -- enumerator -- util: - - `Equals` (to emit `EQUALS` opcode, not needed usually) - - `FromAddress(address string) []byte` - -## Not supported -Due to the limitations of the NEO virtual machine, features listed below will not be supported. -- channels -- goroutines -- returning multiple values from functions +functions) into NEO VM instructions. [Refer to +pkg.go.dev](https://pkg.go.dev/github.com/nspcc-dev/neo-go/pkg/interop) +for full API documentation. In general it provides the same level of +functionality as Neo .net Framework library. ## Quick start -### Compile a smart contract +### Compiling ``` ./bin/neo-go contract compile -i mycontract.go @@ -73,7 +43,7 @@ By default the filename will be the name of your .go file with the .avm extensio ./bin/neo-go contract compile -i mycontract.go --out /Users/foo/bar/contract.avm ``` -### Debugging your smart contract +### Debugging You can dump the opcodes generated by the compiler with the following command: ``` @@ -83,62 +53,143 @@ You can dump the opcodes generated by the compiler with the following command: This will result in something like this: ``` -INDEX OPCODE DESC -0 0x54 PUSH4 -1 0xc5 NEWARRAY -2 0x6b TOALTSTACK -3 0x1 PUSHBYTES1 -3 0x2a * -5 0x6a DUPFROMALTSTACK -6 0x0 PUSH0 -7 0x52 PUSH2 -8 0x7a ROLL -9 0xc4 SETITEM -10 0x6a DUPFROMALTSTACK -11 0x0 PUSH0 -12 0xc3 PICKITEM -13 0x5a PUSH10 -14 0xa2 GTE -15 0x64 JMPIFNOT -16 0x7 7 -16 0x0 0 -18 0x51 PUSH1 -19 0x6c FROMALTSTACK -20 0x75 DROP -21 0x66 RET -22 0x0 PUSH0 -23 0x6c FROMALTSTACK -24 0x75 DROP -25 0x66 RET +INDEX OPCODE PARAMETER +0 INITSLOT 0500 ("\x05\x00") << +3 PUSH0 +4 REVERSEN +5 SYSCALL "\x9a\x1f\x19J" +10 NOP +11 STLOC0 +12 LDLOC0 +13 PUSH1 +14 REVERSEN +15 PUSH1 +16 PACK +17 SYSCALL "\x05\a\x92\x16" +22 NOP +23 PUSH0 +24 REVERSEN +25 SYSCALL "E\x99Z\\" +30 NOP +31 STLOC1 +32 LDLOC1 +33 PUSH1 +34 REVERSEN +35 PUSH1 +36 PACK +37 SYSCALL "\x05\a\x92\x16" +42 NOP +43 PUSH0 +44 REVERSEN +45 SYSCALL "\x87\xc3\xd2d" +50 NOP +51 STLOC2 +52 LDLOC2 +53 PUSH1 +54 REVERSEN +55 PUSH1 +56 PACK +57 SYSCALL "\x05\a\x92\x16" +62 NOP +63 PUSH0 +64 REVERSEN +65 SYSCALL "\x1dY\xe1\x19" +70 NOP +71 STLOC3 +72 LDLOC3 +73 PUSH1 +74 REVERSEN +75 PUSH1 +76 PACK +77 SYSCALL "\x05\a\x92\x16" +82 NOP +83 PUSH1 +84 RET ``` -### 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: +#### Neo Smart Contract Debugger support + +It's possible to debug contracts written in Go using standard [Neo Smart +Contract Debugger](https://github.com/neo-project/neo-debugger/) which is a +part of [Neo Blockchain +Toolkit](https://github.com/neo-project/neo-blockchain-toolkit/). To do that +you need to generate debug information using `--debug` option, like this: ``` -./bin/neo-go contract testinvoke -i mycompiledcontract.avm +$ ./bin/neo-go contract compile -i contract.go -o contract.avm --debug contract.debug.json ``` -Will output something like: -``` -{ - "state": "HALT, BREAK", - "gas_consumed": "0.006", - "Stack": [ - { - "type": "Integer", - "value": "9" - } - ] -} +This file can then be used by debugger and set up to work just like for any +other supported language. + +### Deploying + +Deploying a contract to blockchain with neo-go requires a configuration file +with contract's metadata in YAML format, like the following: ``` +project: + author: Jack Smith + email: jack@example.com + version: 1.0 + name: 'Smart contract' + description: 'Even smarter than Jack himself' + hasstorage: true + hasdynamicinvocation: false + ispayable: false + returntype: ByteArray + parameters: ['String', 'Array'] +``` -At the moment this is implemented via RPC call to the remote server. +It's passed to the `deploy` command via `-c` option: + +``` +$ ./bin/neo-go contract deploy -i contract.avm -c contract.yml -e http://localhost:20331 -w wallet.json -g 0.001 +``` + +Deployment works via an RPC server, an address of which is passed via `-e` +option and should be signed using a wallet from `-w` option. More details can +be found in `deploy` command help. + +#### Neo Express support + +It's possible to deploy contracts written in Go using [Neo +Express](https://github.com/neo-project/neo-express) which is a part of [Neo +Blockchain +Toolkit](https://github.com/neo-project/neo-blockchain-toolkit/). To do that +you need to generate a different metadata file using YAML written for +deployment with neo-go. It's done in the same step with compilation via +`--config` input parameter and `--abi` output parameter, combined with debug +support the command line will look like this: + +``` +$ ./bin/neo-go contract compile -i contract.go --config contract.yml -o contract.avm --debug contract.debug.json --abi contract.abi.json +``` + +This file can then be used by toolkit to deploy contract the same way +contracts in other languagues are deployed. + + +### Invoking +You can import your contract into the standalone VM and run it there (see [VM +documentation](vm.md) for more info), but that only works for simple contracts +that don't use blockchain a lot. For more real contracts you need to deploy +them first and then do test invocations and regular invocations with `contract +testinvokefunction` and `contract invokefunction` commands (or their variants, +see `contract` command help for more details. They all work via RPC, so it's a +mandatory parameter. + +Example call (contract `f84d6a337fbc3d3a201d41da99e86b479e7a2554` with method +`balanceOf` and method's parameter `AK2nJJpJr6o664CWJKi1QRXjqeic2zRp8y` using +given RPC server and wallet and paying 0.00001 GAS for this transaction): + +``` +$ ./bin/neo-go contract invokefunction -e http://localhost:20331 -w my_wallet.json -g 0.00001 f84d6a337fbc3d3a201d41da99e86b479e7a2554 balanceOf AK2nJJpJr6o664CWJKi1QRXjqeic2zRp8y +``` ## Smart contract examples -Some examples are provided in the [examples directory](examples). +Some examples are provided in the [examples directory](../examples). ### Check if the invoker of the contract is the owning address