Merge pull request #956 from nspcc-dev/doc-update-2.x

Documentation update for 2.x
This commit is contained in:
Roman Khimov 2020-05-19 16:02:55 +03:00 committed by GitHub
commit f0d6b0a639
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 1192 additions and 824 deletions

2
.gitignore vendored
View file

@ -31,8 +31,6 @@ TAGS
# leveldb # leveldb
chains/ chains/
chain/ chain/
blockchain/
blockchains/
# patch # patch
*.orig *.orig

View file

@ -110,7 +110,9 @@ mode, after it ends the node can be started normally.
Please refer to [neo-go smart contract development Please refer to [neo-go smart contract development
workshop](https://github.com/nspcc-dev/neo-go-sc-wrkshp) that shows some 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 simple contracts that can be compiled/deployed/run using neo-go compiler, SDK
and private network. 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 # Developer notes
Nodes have such features as [Prometheus](https://prometheus.io/docs/guides/go-application) and Nodes have such features as [Prometheus](https://prometheus.io/docs/guides/go-application) and

View file

@ -2,66 +2,39 @@
The neo-go compiler compiles Go programs to bytecode that the NEO virtual machine can understand. The neo-go compiler compiles Go programs to bytecode that the NEO virtual machine can understand.
## Currently supported ## Language compatibility
### Go internals The compiler is mostly compatible with regular Go language specification, but
- type checking there are some important deviations that you need to be aware of that make it
- multiple assignments a dialect of Go rather than a complete port of the language:
- global variables * `make()` ane `new()` are not supported, most of the time you can substitute
- types int, string, byte and booleans them with composite literals
- struct types + method receives * there is no real distinction between different integer types, all of them
- functions work as big.Int in Go with a limit of 256 bit in width, so you can use
- composite literals `[]int, []string, []byte` `int` for just about anything. This is the way integers work in Neo VM and
- basic if statements adding proper Go types emulation is considered to be too costly.
- binary expressions * goroutines, channels and garbage collection are not supported and will
- return statements never be because emulating that aspects of Go runtime on top of Neo VM is
- for loops close to impossible
- imports * even though `panic()` is supported, `recover()` is not, `panic` shuts the
VM down
* lambdas are not supported
* global variables can't be changed in functions (#638)
* it's not possible to rename imported interop packages, they won't work this
way (#397, #913)
* nested selectors are not yet supported (#957)
* using value variable in range-based loops is not yet supported (#958)
### Go builtins ## VM API (interop layer)
- len
- append
### VM API (interop layer)
Compiler translates interop function calls into NEO VM syscalls or (for custom 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. functions) into NEO VM instructions. [Refer to
pkg.go.dev](https://pkg.go.dev/github.com/nspcc-dev/neo-go/pkg/interop)
#### Standard NEO Smart Contract API for full API documentation. In general it provides the same level of
- account functionality as Neo .net Framework library.
- 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
## Quick start ## Quick start
### Compile a smart contract ### Compiling
``` ```
./bin/neo-go contract compile -i mycontract.go ./bin/neo-go contract compile -i mycontract.go
@ -73,7 +46,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 ./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: You can dump the opcodes generated by the compiler with the following command:
``` ```
@ -112,33 +85,89 @@ INDEX OPCODE DESC
25 0x66 RET 25 0x66 RET
``` ```
### Test invoke a compiled contract #### Neo Smart Contract Debugger support
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:
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: This file can then be used by debugger and set up to work just like for any
``` other supported language.
{
"state": "HALT, BREAK", ### Deploying
"gas_consumed": "0.006",
"Stack": [ Deploying a contract to blockchain with neo-go requires a configuration file
{ with contract's metadata in YAML format, like the following:
"type": "Integer",
"value": "9"
}
]
}
``` ```
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 ## 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 ### Check if the invoker of the contract is the owning address

339
docs/notifications.md Normal file
View file

@ -0,0 +1,339 @@
# Notification subsystem
Original motivation, requirements and general solution strategy are described
in the issue #895.
This extension allows a websocket client to subscribe to various events and
receive them as JSON-RPC notifications from the server.
## Events
Currently supported events:
* new block added
Contents: block.
Filters: none.
* new transaction in the block
Contents: transaction.
Filters: type.
* notification generated during execution
Contents: container hash, contract script hash, stack item.
Filters: contract script hash.
* transaction executed
Contents: application execution result.
Filters: VM state.
## Ordering and persistence guarantees
* new block is only announced after its processing is complete and the chain
is updated to the new height
* no disk-level persistence guarantees are given
* new in-block transaction is announced after block processing, but before
announcing the block itself
* transaction notifications are only announced for successful transactions
* all announcements are being done in the same order they happen on the chain
At first transaction execution is announced, then followed by notifications
generated during this execution, then followed by transaction announcement.
Transaction announcements are ordered the same way they're in the block.
* unsubscription may not cancel pending, but not yet sent events
## Subscription management
Errors are not described down below, but they can be returned as standard
JSON-RPC errors (most often caused by invalid parameters).
### `subscribe` method
Parameters: event stream name, stream-specific filter rules hash (can be
omitted if empty).
Recognized stream names:
* `block_added`
No filter parameters defined.
* `transaction_added`
Filter: `type` as a string containing standard transaction types
(MinerTransaction, InvocationTransaction, etc)
* `notification_from_execution`
Filter: `contract` field containing string with hex-encoded Uint160 (LE
representation).
* `transaction_executed`
Filter: `state` field containing `HALT` or `FAULT` string for successful
and failed executions respectively.
Response: returns subscription ID (string) as a result. This ID can be used to
cancel this subscription and has no meaning other than that.
Example request (subscribe to notifications from contract
0x6293a440ed80a427038e175a507d3def1e04fb67 generated when executing
transactions):
```
{
"jsonrpc": "2.0",
"method": "subscribe",
"params": ["notification_from_execution", {"contract": "6293a440ed80a427038e175a507d3def1e04fb67"}],
"id": 1
}
```
Example response:
```
{
"jsonrpc": "2.0",
"id": 1,
"result": "55aaff00"
}
```
### `unsubscribe` method
Parameters: subscription ID as a string.
Response: boolean true.
Example request (unsubscribe from "55aaff00"):
```
{
"jsonrpc": "2.0",
"method": "unsubscribe",
"params": ["55aaff00"],
"id": 1
}
```
Example response:
```
{
"jsonrpc": "2.0",
"id": 1,
"result": true
}
```
## Events
Events are sent as JSON-RPC notifications from the server with `method` field
being used for notification names. Notification names are identical to stream
names described for `subscribe` method with one important addition for
`event_missed` which can be sent for any subscription to signify that some
events were not delivered (usually when client isn't able to keep up with
event flow).
Verbose responses for various structures like blocks and transactions are used
to simplify working with notifications on client side. Returned structures
mostly follow the one used by standard Neo RPC calls, but may have some minor
differences.
### `block_added` notification
As a first parameter (`params` section) contains block converted to JSON
structure which is similar to verbose `getblock` response but with the
following differences:
* it doesn't have `size` field (you can calculate it client-side)
* it doesn't have `nextblockhash` field (it's supposed to be the latest one
anyway)
* it doesn't have `confirmations` field (see previous)
* transactions contained don't have `net_fee` and `sys_fee` fields
No other parameters are sent.
Example:
```
{
"jsonrpc" : "2.0",
"method" : "block_added",
"params" : [
{
"previousblockhash" : "0x33f3e0e24542b2ec3b6420e6881c31f6460a39a4e733d88f7557cbcc3b5ed560",
"nextconsensus" : "AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU",
"index" : 205,
"nonce" : "0000000000000457",
"version" : 0,
"tx" : [
{
"version" : 0,
"attributes" : [],
"txid" : "0xf9adfde059810f37b3d0686d67f6b29034e0c669537df7e59b40c14a0508b9ed",
"size" : 10,
"vin" : [],
"type" : "MinerTransaction",
"scripts" : [],
"vout" : []
},
{
"version" : 1,
"txid" : "0x93670859cc8a42f6ea994869c944879678d33d7501d388f5a446a8c7de147df7",
"attributes" : [],
"size" : 60,
"script" : "097465737476616c756507746573746b657952c103507574676f20ccfbd5f01d5b9633387428b8bab95a9e78c2",
"vin" : [],
"scripts" : [],
"type" : "InvocationTransaction",
"vout" : []
}
],
"time" : 1586154525,
"hash" : "0x48fba8aebf88278818a3dc0caecb230873d1d4ce1ea8bf473634317f94a609e5",
"script" : {
"invocation" : "4047a444a51218ac856f1cbc629f251c7c88187910534d6ba87847c86a9a73ed4951d203fd0a87f3e65657a7259269473896841f65c0a0c8efc79d270d917f4ff640435ee2f073c94a02f0276dfe4465037475e44e1c34c0decb87ec9c2f43edf688059fc4366a41c673d72ba772b4782c39e79f01cb981247353216d52d2df1651140527eb0dfd80a800fdd7ac8fbe68fc9366db2d71655d8ba235525a97a69a7181b1e069b82091be711c25e504a17c3c55eee6e76e6af13cb488fbe35d5c5d025c34041f39a02ebe9bb08be0e4aaa890f447dc9453209bbfb4705d8f2d869c2b55ee2d41dbec2ee476a059d77fb7c26400284328d05aece5f3168b48f1db1c6f7be0b",
"verification" : "532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae"
},
"merkleroot" : "0x9d922c5cfd4c8cd1da7a6b2265061998dc438bd0dea7145192e2858155e6c57a"
}
]
}
```
### `transaction_added` notification
In the first parameter (`params` section) contains transaction converted to
JSON which is similar to verbose `getrawtransaction` response, but with the
following differences:
* `net_fee` and `sys_fee` fields are always missing
* block's metadata is missing (`blockhash`, `confirmations`, `blocktime`)
No other parameters are sent.
Example:
```
{
"params" : [
{
"vin" : [],
"scripts" : [],
"attributes" : [],
"txid" : "0x93670859cc8a42f6ea994869c944879678d33d7501d388f5a446a8c7de147df7",
"size" : 60,
"vout" : [],
"type" : "InvocationTransaction",
"version" : 1,
"script" : "097465737476616c756507746573746b657952c103507574676f20ccfbd5f01d5b9633387428b8bab95a9e78c2"
}
],
"method" : "transaction_added",
"jsonrpc" : "2.0"
}
```
### `notification_from_execution` notification
Contains three parameters: container hash (hex-encoded LE Uint256 in a
string), contract script hash (hex-encoded LE Uint160 in a string) and stack
item (encoded the same way as `state` field contents for notifications from
`getapplicationlog` response).
Example:
```
{
"method" : "notification_from_execution",
"jsonrpc" : "2.0",
"params" : [
{
"state" : {
"value" : [
{
"value" : "636f6e74726163742063616c6c",
"type" : "ByteArray"
},
{
"value" : "507574",
"type" : "ByteArray"
},
{
"value" : [
{
"type" : "ByteArray",
"value" : "746573746b6579"
},
{
"value" : "7465737476616c7565",
"type" : "ByteArray"
}
],
"type" : "Array"
}
],
"type" : "Array"
},
"contract" : "0xc2789e5ab9bab828743833965b1df0d5fbcc206f"
}
]
}
```
### `transaction_executed` notification
Contains the same result as from `getapplicationlog` method in the first
parameter and no other parameters. One difference from `getapplicationlog` is
that it always contains zero in the `contract` field.
Example:
```
{
"method" : "transaction_executed",
"params" : [
{
"executions" : [
{
"vmstate" : "HALT",
"contract" : "0x0000000000000000000000000000000000000000",
"notifications" : [
{
"state" : {
"type" : "Array",
"value" : [
{
"type" : "ByteArray",
"value" : "636f6e74726163742063616c6c"
},
{
"type" : "ByteArray",
"value" : "507574"
},
{
"value" : [
{
"value" : "746573746b6579",
"type" : "ByteArray"
},
{
"type" : "ByteArray",
"value" : "7465737476616c7565"
}
],
"type" : "Array"
}
]
},
"contract" : "0xc2789e5ab9bab828743833965b1df0d5fbcc206f"
}
],
"gas_consumed" : "1.048",
"stack" : [
{
"type" : "Integer",
"value" : "1"
}
],
"trigger" : "Application"
}
],
"txid" : "0x93670859cc8a42f6ea994869c944879678d33d7501d388f5a446a8c7de147df7"
}
],
"jsonrpc" : "2.0"
}
```
### `event_missed` notification
Never has any parameters. Example:
```
{
"jsonrpc": "2.0",
"method": "event_missed",
"params": []
}
```

View file

@ -65,6 +65,18 @@ which would yield the response:
| `submitblock` | | `submitblock` |
| `validateaddress` | | `validateaddress` |
#### Implementation notices
##### `invokefunction` and `invoke`
neo-go's implementation of `invokefunction` and `invoke` does not return `tx`
field in the answer because that requires signing the transaction with some
key in the server which doesn't fit the model of our node-client interactions.
Lacking this signature the transaction is almost useless, so there is no point
in returning it.
Both methods also don't currently support arrays in function parameters.
### Unsupported methods ### Unsupported methods
Methods listed down below are not going to be supported for various reasons Methods listed down below are not going to be supported for various reasons
@ -86,17 +98,24 @@ and we're not accepting issues related to them.
| `sendmany` | Not applicable to neo-go, see `claimgas` comment | | `sendmany` | Not applicable to neo-go, see `claimgas` comment |
| `sendtoaddress` | Not applicable to neo-go, see `claimgas` comment | | `sendtoaddress` | Not applicable to neo-go, see `claimgas` comment |
#### Implementation notices ### Extensions
##### `invokefunction` and `invoke` Some additional extensions are implemented as a part of this RPC server.
neo-go's implementation of `invokefunction` and `invoke` does not return `tx` #### Websocket server
field in the answer because that requires signing the transaction with some
key in the server which doesn't fit the model of our node-client interactions.
Lacking this signature the transaction is almost useless, so there is no point
in returning it.
Both methods also don't currently support arrays in function parameters. This server accepts websocket connections on `ws://$BASE_URL/ws` address. You
can use it to perform regular RPC calls over websockets (it's supposed to be a
little faster than going regular HTTP route) and you can also use it for
additional functionality provided only via websockets (like notifications).
#### Notification subsystem
Notification subsystem consists of two additional RPC methods (`subscribe` and
`unsubscribe` working only over websocket connection) that allow to subscribe
to various blockchain events (with simple event filtering) and receive them on
the client as JSON-RPC notifications. More details on that are written in the
[notifications specification](notifications.md).
## Reference ## Reference

View file

@ -1,523 +0,0 @@
# Runtime
A brief overview of NEO smart contract API's that can be used in the neo-go framework.
# Overview
1. [Account]()
2. [Asset]()
3. [Attribute]()
4. [Block]()
5. [Blockchain]()
6. [Contract]()
7. [Crypto]()
8. [Engine]()
9. [Enumerator]()
10. [Iterator]()
11. [Header]()
12. [Input]()
13. [Output]()
14. [Runtime]()
15. [Storage]()
16. [Transaction]()
17. [Util]()
## Account
#### GetScriptHash
```
GetScriptHash(a Account) []byte
```
Returns the script hash of the given account.
#### GetVotes
```
GetVotes(a Account) [][]byte
```
Returns the the votes (a slice of public keys) of the given account.
#### GetBalance
```
GetBalance(a Account, assetID []byte) int
```
Returns the balance of the given asset id for the given account.
## Asset
#### GetAssetID
```
GetAssetID(a Asset) []byte
```
Returns the id of the given asset.
#### GetAmount
```
GetAmount(a Asset) int
```
Returns the amount of the given asset id.
#### GetAvailable
```
GetAvailable(a Asset) int
```
Returns the available amount of the given asset.
#### GetPrecision
```
GetPrecision(a Asset) byte
```
Returns the precision of the given Asset.
#### GetOwner
```
GetOwner(a Asset) []byte
```
Returns the owner of the given asset.
#### GetAdmin
```
GetAdmin(a Asset) []byte
```
Returns the admin of the given asset.
#### GetIssuer
```
GetIssuer(a Asset) []byte
```
Returns the issuer of the given asset.
#### Create
```
Create(type byte, name string, amount int, precision byte, owner, admin, issuer []byte)
```
Creates a new asset on the blockchain.
#### Renew
```
Renew(asset Asset, years int)
```
Renews the given asset as long as the given years.
## Attribute
#### GetUsage
```
GetUsage(attr Attribute) []byte
```
Returns the usage of the given attribute.
#### GetData
```
GetData(attr Attribute) []byte
```
Returns the data of the given attribute.
## Block
#### GetTransactionCount
```
GetTransactionCount(b Block) int
```
Returns the number of transactions that are recorded in the given block.
#### GetTransactions
```
GetTransactions(b Block) []transaction.Transaction
```
Returns a slice of the transactions that are recorded in the given block.
#### GetTransaction
```
GetTransaction(b Block, hash []byte) transaction.Transaction
```
Returns the transaction by the given hash that is recorded in the given block.
## Blockchain
#### GetHeight
```
GetHeight() int
```
Returns the current height of the blockchain.
#### GetHeader
```
GetHeader(heightOrHash []interface{}) header.Header
```
Return the header by the given hash or index.
#### GetBlock
```
GetBlock(heightOrHash interface{}) block.Block
```
Returns the block by the given hash or index.
#### GetTransaction
```
GetTransaction(hash []byte) transaction.Transaction
```
Returns a transaction by the given hash.
#### GetContract
```
GetContract(scriptHash []byte) contract.Contract
```
Returns the contract found by the given script hash.
#### GetAccount
```
GetAccount(scriptHash []byte) account.Account
```
Returns the account found by the given script hash.
#### GetValiditors
```
GetValidators() [][]byte
```
Returns a list of validators public keys.
#### GetAsset
```
GetAsset(assetID []byte) asset.Asset
```
Returns the asset found by the given asset id.
## Contract
#### GetScript
```
GetScript(c Contract) []byte
```
Return the script of the given contract.
#### IsPayable
```
IsPayable(c Contract) bool
```
Returns whether the given contract is payable.
#### GetStorageContext
```
GetStorageContext(c Contract)
```
Returns the storage context of the given contract.
#### Create
```
Create(
script []byte,
params []interface{},
returnType byte,
properties interface{},
name,
version,
author,
email,
description string)
```
Creates a new contract on the blockchain.
#### Migrate
```
Migrate(
script []byte,
params []interface{},
returnType byte,
properties interface{},
name,
version,
author,
email,
description string)
```
Migrates a contract on the blockchain.
#### Destroy
```
Destroy(c Contract)
```
Deletes the given contract from the blockchain.
## Crypto
#### SHA1
```
SHA1(data []byte) []byte
```
Computes the sha1 hash of the given bytes
#### SHA256
```
SHA256(data []byte) []byte
```
Computes the sha256 hash of the given bytes
#### Hash256
```
Hash256(data []byte) []byte
```
Computes the sha256^2 of the given data.
#### Hash160
```
Hash160(data []byte) []byte) []byte
```
Computes the ripemd160 over the sha256 hash of the given data.
## Engine
#### GetScriptContainer
```
GetScriptContainer() transaction.Transaction
```
Returns the transaction that is in the context of the VM execution.
#### GetExecutingScriptHash
```
GetExecutingScriptHash() []byte
```
Returns the script hash of the contract that is currently being executed.
#### GetCallingScriptHash
```
GetCallingScriptHash() []byte
```
Returns the script hash of the contract that has started the execution of the current script.
#### GetEntryScriptHash
```
GetEntryScriptHash() []byte
```
Returns the script hash of the contract that started the execution from the start.
## Enumerator
#### Create
```
Create(items []inteface{}) Enumerator
```
Create a enumerator from the given items.
#### Next
```
Next(e Enumerator) interface{}
```
Returns the next item from the given enumerator.
#### Value
```
Value(e Enumerator) interface{}
```
Returns the enumerator value.
## Iterator
#### Create
```
Create(items []inteface{}) Iterator
```
Creates an iterator from the given items.
#### Key
```
Key(it Iterator) interface{}
```
Return the key from the given iterator.
#### Keys
```
Keys(it Iterator) []interface{}
```
Returns the iterator's keys
#### Values
```
Values(it Iterator) []interface{}
```
Returns the iterator's values
## Header
#### GetIndex
```
GetIndex(h Header) int
```
Returns the height of the given header.
#### GetHash
```
GetHash(h Header) []byte
```
Returns the hash of the given header.
#### GetPrevHash
```
GetPrevhash(h Header) []byte
```
Returns the previous hash of the given header.
#### GetTimestamp
```
GetTimestamp(h Header) int
```
Returns the timestamp of the given header.
#### GetVersion
```
GetVersion(h Header) int
```
Returns the version of the given header.
#### GetMerkleroot
```
GetMerkleRoot(h Header) []byte
```
Returns the merkle root of the given header.
#### GetConsensusData
```
GetConsensusData(h Header) int
```
Returns the consensus data of the given header.
#### GetNextConsensus
```
GetNextConsensus(h Header) []byte
```
Returns the next consensus of the given header.
## Input
#### GetHash
```
GetHash(in Input) []byte
```
Returns the hash field of the given input.
#### GetIndex
```
GetIndex(in Input) int
```
Returns the index field of the given input.
## Output
#### GetAssetID
```
GetAssetId(out Output) []byte
```
Returns the asset id field of the given output.
#### GetValue
```
GetValue(out Output) int
```
Returns the value field of the given output.
#### GetScriptHash
```
GetScriptHash(out Output) []byte
```
Returns the script hash field of the given output.
## Runtime
#### CheckWitness
```
CheckWitness(hash []byte) bool
```
Verifies if the given hash is the hash of the contract owner.
#### Log
```
Log(message string)
```
Logs the given message.
#### Notify
```
Notify(args ...interface{}) int
```
Notify any number of arguments to the VM.
#### GetTime
```
GetTime() int
```
Returns the current time based on the highest block in the chain.
#### GetTrigger
```
GetTrigger() byte
```
Returns the trigger type of the execution.
#### Serialize
```
Serialize(item interface{}) []byte
```
Serialize the given stack item to a slice of bytes.
#### Deserialize
```
Deserialize(data []byte) interface{}
```
Deserializes the given data to a stack item.
## Storage
#### GetContext
```
GetContext() Context
```
Returns the current storage context.
#### Put
```
Put(ctx Context, key, value []interface{})
```
Stores the given value at the given key.
#### Get
```
Get(ctx Context, key interface{}) interface{}
```
Returns the value found at the given key.
#### Delete
```
Delete(ctx Context, key interface{})
```
Delete's the given key from storage.
#### Find
```
Find(ctx Context, key interface{}) iterator.Iterator
```
Find returns an iterator key-values that match the given key.
## Transaction
#### GetHash
```
GetHash(t Transacfion) []byte
```
Returns the hash for the given transaction.
#### GetType
```
GetType(t Transacfion) byte
```
Returns the type of the given transaction.
#### GetAttributes
```
GetAttributes(t Transacfion) []attribute.Attribute
```
Returns the attributes of the given transaction.
#### GetReferences
```
GetReferences(t Transacfion) interface{}
```
Returns the references of the given transaction.
#### GetUnspentCoins
```
GetUnspentCoins(t Transacfion) interface{}
```
Returns the unspent coins of the given transaction.
#### GetOutputs
```
GetOutputs(t Transacfion) []output.Output
```
Returns the outputs of the given transaction
#### GetInputs
```
GetInputs(t Transacfion) []input.Input
```
Returns the inputs of the given transaction

View file

@ -16,7 +16,7 @@ var (
"SHA1", "Hash256", "Hash160", "SHA1", "Hash256", "Hash160",
"VerifySignature", "AppCall", "VerifySignature", "AppCall",
"FromAddress", "Equals", "FromAddress", "Equals",
"panic", "panic", "DynAppCall",
} }
) )

View file

@ -1085,14 +1085,23 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) {
emit.Opcode(c.prog.BinWriter, opcode.HASH160) emit.Opcode(c.prog.BinWriter, opcode.HASH160)
case "VerifySignature": case "VerifySignature":
emit.Opcode(c.prog.BinWriter, opcode.VERIFY) emit.Opcode(c.prog.BinWriter, opcode.VERIFY)
case "AppCall": case "AppCall", "DynAppCall":
numArgs := len(expr.Args) - 1 numArgs := len(expr.Args)
if name == "AppCall" {
numArgs--
}
c.emitReverse(numArgs) c.emitReverse(numArgs)
emit.Opcode(c.prog.BinWriter, opcode.APPCALL) emit.Opcode(c.prog.BinWriter, opcode.APPCALL)
buf := c.getByteArray(expr.Args[0]) var buf []byte
if len(buf) != 20 { if name == "AppCall" {
c.prog.Err = errors.New("invalid script hash") buf = c.getByteArray(expr.Args[0])
if len(buf) != 20 {
c.prog.Err = errors.New("invalid script hash")
}
} else {
// Zeroes for DynAppCall.
buf = make([]byte, 20)
} }
c.prog.WriteBytes(buf) c.prog.WriteBytes(buf)

View file

@ -9,6 +9,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/crypto/hash"
"github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -52,6 +53,19 @@ func TestFromAddress(t *testing.T) {
} }
func TestAppCall(t *testing.T) { func TestAppCall(t *testing.T) {
const srcDynApp = `
package foo
import "github.com/nspcc-dev/neo-go/pkg/interop/engine"
func Main(h []byte) []byte {
x := []byte{1, 2}
y := []byte{3, 4}
result := engine.DynAppCall(h, x, y)
return result.([]byte)
}
`
var hasDynamicInvoke bool
srcInner := ` srcInner := `
package foo package foo
func Main(a []byte, b []byte) []byte { func Main(a []byte, b []byte) []byte {
@ -62,14 +76,31 @@ func TestAppCall(t *testing.T) {
inner, err := compiler.Compile(strings.NewReader(srcInner)) inner, err := compiler.Compile(strings.NewReader(srcInner))
require.NoError(t, err) require.NoError(t, err)
dynapp, err := compiler.Compile(strings.NewReader(srcDynApp))
require.NoError(t, err)
ih := hash.Hash160(inner) ih := hash.Hash160(inner)
dh := hash.Hash160(dynapp)
getScript := func(u util.Uint160) ([]byte, bool) { getScript := func(u util.Uint160) ([]byte, bool) {
if u.Equals(ih) { if u.Equals(ih) {
return inner, true return inner, true
} }
if u.Equals(dh) {
return dynapp, hasDynamicInvoke
}
return nil, false return nil, false
} }
dynEntryScript := `
package foo
import "github.com/nspcc-dev/neo-go/pkg/interop/engine"
func Main(h []byte) interface{} {
return engine.AppCall(` + fmt.Sprintf("%#v", dh.BytesBE()) + `, h)
}
`
dynentry, err := compiler.Compile(strings.NewReader(dynEntryScript))
require.NoError(t, err)
t.Run("valid script", func(t *testing.T) { t.Run("valid script", func(t *testing.T) {
src := getAppCallScript(fmt.Sprintf("%#v", ih.BytesBE())) src := getAppCallScript(fmt.Sprintf("%#v", ih.BytesBE()))
v := vmAndCompile(t, src) v := vmAndCompile(t, src)
@ -118,6 +149,38 @@ func TestAppCall(t *testing.T) {
assertResult(t, v, []byte{1, 2, 3, 4}) assertResult(t, v, []byte{1, 2, 3, 4})
}) })
t.Run("dynamic", func(t *testing.T) {
t.Run("valid script", func(t *testing.T) {
hasDynamicInvoke = true
v := vm.New()
v.Load(dynentry)
v.SetScriptGetter(getScript)
v.Estack().PushVal(ih.BytesBE())
require.NoError(t, v.Run())
assertResult(t, v, []byte{1, 2, 3, 4})
})
t.Run("invalid script", func(t *testing.T) {
hasDynamicInvoke = true
v := vm.New()
v.Load(dynentry)
v.SetScriptGetter(getScript)
v.Estack().PushVal([]byte{1})
require.Error(t, v.Run())
})
t.Run("no dynamic invoke", func(t *testing.T) {
hasDynamicInvoke = false
v := vm.New()
v.Load(dynentry)
v.SetScriptGetter(getScript)
v.Estack().PushVal(ih.BytesBE())
require.Error(t, v.Run())
})
})
} }
func getAppCallScript(h string) string { func getAppCallScript(h string) string {

View file

@ -1,12 +1,30 @@
package compiler package compiler
var syscalls = map[string]map[string]string{ var syscalls = map[string]map[string]string{
"account": {
"GetBalance": "Neo.Account.GetBalance",
"GetScriptHash": "Neo.Account.GetScriptHash",
"GetVotes": "Neo.Account.GetVotes",
"IsStandard": "Neo.Account.IsStandard",
},
"attribute": {
"GetUsage": "Neo.Attribute.GetUsage",
"GetData": "Neo.Attribute.GetData",
},
"enumerator": {
"Concat": "Neo.Enumerator.Concat",
"Create": "Neo.Enumerator.Create",
"Next": "Neo.Enumerator.Next",
"Value": "Neo.Enumerator.Value",
},
"storage": { "storage": {
"GetContext": "Neo.Storage.GetContext", "ConvertContextToReadOnly": "Neo.StorageContext.AsReadOnly",
"Put": "Neo.Storage.Put", "Delete": "Neo.Storage.Delete",
"Get": "Neo.Storage.Get", "Find": "Neo.Storage.Find",
"Delete": "Neo.Storage.Delete", "Get": "Neo.Storage.Get",
"Find": "Neo.Storage.Find", "GetContext": "Neo.Storage.GetContext",
"GetReadOnlyContext": "Neo.Storage.GetReadOnlyContext",
"Put": "Neo.Storage.Put",
}, },
"runtime": { "runtime": {
"GetTrigger": "Neo.Runtime.GetTrigger", "GetTrigger": "Neo.Runtime.GetTrigger",
@ -18,14 +36,15 @@ var syscalls = map[string]map[string]string{
"Deserialize": "Neo.Runtime.Deserialize", "Deserialize": "Neo.Runtime.Deserialize",
}, },
"blockchain": { "blockchain": {
"GetHeight": "Neo.Blockchain.GetHeight", "GetAccount": "Neo.Blockchain.GetAccount",
"GetHeader": "Neo.Blockchain.GetHeader", "GetAsset": "Neo.Blockchain.GetAsset",
"GetBlock": "Neo.Blockchain.GetBlock", "GetBlock": "Neo.Blockchain.GetBlock",
"GetTransaction": "Neo.Blockchain.GetTransaction", "GetContract": "Neo.Blockchain.GetContract",
"GetContract": "Neo.Blockchain.GetContract", "GetHeader": "Neo.Blockchain.GetHeader",
"GetAccount": "Neo.Blockchain.GetAccount", "GetHeight": "Neo.Blockchain.GetHeight",
"GetValidators": "Neo.Blockchain.GetValidators", "GetTransaction": "Neo.Blockchain.GetTransaction",
"GetAsset": "Neo.Blockchain.GetAsset", "GetTransactionHeight": "Neo.Blockchain.GetTransactionHeight",
"GetValidators": "Neo.Blockchain.GetValidators",
}, },
"header": { "header": {
"GetIndex": "Neo.Header.GetIndex", "GetIndex": "Neo.Header.GetIndex",
@ -43,20 +62,25 @@ var syscalls = map[string]map[string]string{
"GetTransaction": "Neo.Block.GetTransaction", "GetTransaction": "Neo.Block.GetTransaction",
}, },
"transaction": { "transaction": {
"GetHash": "Neo.Transaction.GetHash", "GetAttributes": "Neo.Transaction.GetAttributes",
"GetType": "Neo.Transaction.GetType", "GetHash": "Neo.Transaction.GetHash",
"GetAttributes": "Neo.Transaction.GetAttributes", "GetInputs": "Neo.Transaction.GetInputs",
"GetInputs": "Neo.Transaction.GetInputs", "GetOutputs": "Neo.Transaction.GetOutputs",
"GetOutputs": "Neo.Transaction.GetOutputs", "GetReferences": "Neo.Transaction.GetReferences",
"GetReferences": "Neo.Transaction.GetReferences", "GetScript": "Neo.InvocationTransaction.GetScript",
"GetUnspentCoins": "Neo.Transaction.GetUnspentCoins", "GetType": "Neo.Transaction.GetType",
"GetScript": "Neo.Transaction.GetScript", "GetWitnesses": "Neo.Transaction.GetWitnesses",
}, },
"asset": { "asset": {
"Create": "Neo.Asset.Create",
"GetAdmin": "Neo.Asset.GetAdmin",
"GetAmount": "Neo.Asset.GetAmount",
"GetAssetID": "Neo.Asset.GetAssetID", "GetAssetID": "Neo.Asset.GetAssetID",
"GetAssetType": "Neo.Asset.GetAssetType", "GetAssetType": "Neo.Asset.GetAssetType",
"GetAmount": "Neo.Asset.GetAmount", "GetAvailable": "Neo.Asset.GetAvailable",
"Create": "Neo.Asset.Create", "GetIssuer": "Neo.Asset.GetIssuer",
"GetOwner": "Neo.Asset.GetOwner",
"GetPrecision": "Neo.Asset.GetPrecision",
"Renew": "Neo.Asset.Renew", "Renew": "Neo.Asset.Renew",
}, },
"contract": { "contract": {
@ -83,6 +107,7 @@ var syscalls = map[string]map[string]string{
"GetExecutingScriptHash": "System.ExecutionEngine.GetExecutingScriptHash", "GetExecutingScriptHash": "System.ExecutionEngine.GetExecutingScriptHash",
}, },
"iterator": { "iterator": {
"Concat": "Neo.Iterator.Concat",
"Create": "Neo.Iterator.Create", "Create": "Neo.Iterator.Create",
"Key": "Neo.Iterator.Key", "Key": "Neo.Iterator.Key",
"Keys": "Neo.Iterator.Keys", "Keys": "Neo.Iterator.Keys",
@ -90,4 +115,7 @@ var syscalls = map[string]map[string]string{
"Value": "Neo.Iterator.Value", "Value": "Neo.Iterator.Value",
"Values": "Neo.Iterator.Values", "Values": "Neo.Iterator.Values",
}, },
"witness": {
"GetVerificationScript": "Neo.Witness.GetVerificationScript",
},
} }

View file

@ -236,7 +236,14 @@ func (ic *interopContext) witnessGetVerificationScript(v *vm.VM) error {
// bcGetValidators returns validators. // bcGetValidators returns validators.
func (ic *interopContext) bcGetValidators(v *vm.VM) error { func (ic *interopContext) bcGetValidators(v *vm.VM) error {
validators := ic.dao.GetValidators() valStates := ic.dao.GetValidators()
if len(valStates) > vm.MaxArraySize {
return errors.New("too many validators")
}
validators := make([]vm.StackItem, 0, len(valStates))
for _, val := range valStates {
validators = append(validators, vm.NewByteArrayItem(val.PublicKey.Bytes()))
}
v.Estack().PushVal(validators) v.Estack().PushVal(validators)
return nil return nil
} }

View file

@ -575,8 +575,12 @@ func (ic *interopContext) contractGetStorageContext(v *vm.VM) error {
if !ok { if !ok {
return fmt.Errorf("%T is not a contract state", cs) return fmt.Errorf("%T is not a contract state", cs)
} }
contractState, err := ic.dao.GetContractState(cs.ScriptHash()) _, err := ic.dao.GetContractState(cs.ScriptHash())
if contractState == nil || err != nil { if err != nil {
return fmt.Errorf("non-existent contract")
}
_, err = ic.lowerDao.GetContractState(cs.ScriptHash())
if err == nil {
return fmt.Errorf("contract was not created in this transaction") return fmt.Errorf("contract was not created in this transaction")
} }
stc := &StorageContext{ stc := &StorageContext{

View file

@ -27,6 +27,7 @@ type interopContext struct {
block *block.Block block *block.Block
tx *transaction.Transaction tx *transaction.Transaction
dao *dao.Cached dao *dao.Cached
lowerDao dao.DAO
notifications []state.NotificationEvent notifications []state.NotificationEvent
log *zap.Logger log *zap.Logger
} }
@ -34,7 +35,7 @@ type interopContext struct {
func newInteropContext(trigger trigger.Type, bc Blockchainer, d dao.DAO, block *block.Block, tx *transaction.Transaction, log *zap.Logger) *interopContext { func newInteropContext(trigger trigger.Type, bc Blockchainer, d dao.DAO, block *block.Block, tx *transaction.Transaction, log *zap.Logger) *interopContext {
dao := dao.NewCached(d) dao := dao.NewCached(d)
nes := make([]state.NotificationEvent, 0) nes := make([]state.NotificationEvent, 0)
return &interopContext{bc, trigger, block, tx, dao, nes, log} return &interopContext{bc, trigger, block, tx, dao, d, nes, log}
} }
// SpawnVM returns a VM with script getter and interop functions set // SpawnVM returns a VM with script getter and interop functions set

View file

@ -1,23 +1,43 @@
/*
Package account provides getter functions for Account interop structure.
To use these functions you need to get an Account first via blockchain.GetAccount
call.
*/
package account package account
// Package account provides function signatures that can be used inside // Account represents NEO account type that is used in interop functions, it's
// smart contracts that are written in the neo-go framework. // an opaque data structure that you can get data from only using functions from
// this package. It's similar in function to the Account class in the Neo .net
// Account stubs a NEO account type. // framework.
type Account struct{} type Account struct{}
// GetScriptHash returns the script hash of the given account. // GetScriptHash returns the script hash of the given Account (20 bytes in BE
// representation). It uses `Neo.Account.GetBalance` syscall internally.
func GetScriptHash(a Account) []byte { func GetScriptHash(a Account) []byte {
return nil return nil
} }
// GetVotes returns the votes of the given account which should be a slice of // GetVotes returns current votes of the given account represented as a slice of
// public key raw bytes. // public keys. Keys are serialized into byte slices in their compressed form (33
// bytes long each). This function uses `Neo.Account.GetVotes` syscall
// internally.
func GetVotes(a Account) [][]byte { func GetVotes(a Account) [][]byte {
return nil return nil
} }
// GetBalance returns the balance of for the given account and asset id. // GetBalance returns current balance of the given asset (by its ID, 256 bit
// hash in BE form) for the given account. Only native UTXO assets can be
// queiried via this function, for NEP-5 ones use respective contract calls.
// The value returned is represented as an integer with original value multiplied
// by 10⁸ so you can work with fractional parts of the balance too. This function
// uses `Neo.Account.GetBalance` syscall internally.
func GetBalance(a Account, assetID []byte) int { func GetBalance(a Account, assetID []byte) int {
return 0 return 0
} }
// IsStandard checks whether given account uses standard (CHECKSIG or
// CHECKMULTISIG) contract. It only works for deployed contracts and uses
// `Neo.Account.IsStandard` syscall internally.
func IsStandard(a Account) bool {
return false
}

View file

@ -1,53 +1,97 @@
/*
Package asset provides functions to work with regular UTXO assets (like NEO or GAS).
Mostly these are getters for Asset structure, but you can also create new assets
and renew them (although it's recommended to use NEP-5 standard for new tokens).
*/
package asset package asset
// Package asset provides function signatures that can be used inside // Asset represents NEO asset type that is used in interop functions, it's
// smart contracts that are written in the neo-go framework. // an opaque data structure that you can get data from only using functions from
// this package. It's similar in function to the Asset class in the Neo .net
// Asset stubs a NEO asset type. // framework. To be able to use it you either need to get an existing Asset via
// blockchain.GetAsset function or create a new one via Create.
type Asset struct{} type Asset struct{}
// GetAssetID returns the id of the given asset. // GetAssetID returns ID (256-bit ID of Register transaction for this asset in BE
// representation) of the given asset. It uses `Neo.Asset.GetAssetId` syscall
// internally.
func GetAssetID(a Asset) []byte { func GetAssetID(a Asset) []byte {
return nil return nil
} }
// GetAssetType returns the type of the given asset. // GetAssetType returns type of the given asset as a byte value. The value
// returned can be interpreted as a bit field with the following meaning:
// CreditFlag = 0x40
// DutyFlag = 0x80
// SystemShare = 0x00
// SystemCoin = 0x01
// Currency = 0x08
// Share = DutyFlag | 0x10
// Invoice = DutyFlag | 0x18
// Token = CreditFlag | 0x20
// It uses `Neo.Asset.GetAssetType` syscall internally.
func GetAssetType(a Asset) byte { func GetAssetType(a Asset) byte {
return 0x00 return 0x00
} }
// GetAmount returns the amount of the given asset. // GetAmount returns the total amount of the given asset as an integer
// multiplied by 10⁸. This value is the maximum possible circulating quantity of
// Asset. The function uses `Neo.Asset.GetAmount` syscall internally.
func GetAmount(a Asset) int { func GetAmount(a Asset) int {
return 0 return 0
} }
// GetAvailable returns the available of the given asset. // GetAvailable returns the amount of Asset currently available on the
// blockchain. It uses the same encoding as the result of GetAmount and its
// value can never exceed the value returned by GetAmount. This function uses
// `Neo.Asset.GetAvailable` syscall internally.
func GetAvailable(a Asset) int { func GetAvailable(a Asset) int {
return 0 return 0
} }
// GetPrecision returns the precision of the given asset. // GetPrecision returns precision of the given Asset. It uses
// `Neo.Asset.GetPrecision` syscall internally.
func GetPrecision(a Asset) byte { func GetPrecision(a Asset) byte {
return 0x00 return 0x00
} }
// GetOwner returns the owner of the given asset. // GetOwner returns the owner of the given Asset. It's represented as a
// serialized (in compressed form) public key (33 bytes long). This function
// uses `Neo.Asset.GetOwner` syscall internally.
func GetOwner(a Asset) []byte { func GetOwner(a Asset) []byte {
return nil return nil
} }
// GetAdmin returns the admin of the given asset. // GetAdmin returns the admin of the given Asset represented as a 160 bit hash
// in BE form (contract script hash). Admin can modify attributes of this Asset.
// This function uses `Neo.Asset.GetAdmin` syscall internally.
func GetAdmin(a Asset) []byte { func GetAdmin(a Asset) []byte {
return nil return nil
} }
// GetIssuer returns the issuer of the given asset. // GetIssuer returns the issuer of the given Asset represented as a 160 bit hash
// in BE form (contract script hash). Issuer can issue new tokens for this Asset.
// This function uses `Neo.Asset.GetIssuer` syscall internally.
func GetIssuer(a Asset) []byte { func GetIssuer(a Asset) []byte {
return nil return nil
} }
// Create registers a new asset on the blockchain. // Create registers a new asset on the blockchain (similar to old Register
func Create(assetType byte, name string, amount int, precision byte, owner, admin, issuer []byte) {} // transaction). `assetType` parameter has the same set of possible values as
// GetAssetType result, `amount` must be multiplied by 10⁸, `precision` limits
// the smallest possible amount of new Asset to 10⁻ⁿ (where n is precision which
// can't exceed 8), `owner` is a public key of the owner in compressed serialized
// form (33 bytes), `admin` and `issuer` should be represented as 20-byte slices
// storing 160-bit hash in BE form. Created Asset is set to expire in one year,
// so you need to renew it in time. If successful, this function returns a new
// Asset. It uses `Neo.Asset.Create` syscall internally.
func Create(assetType byte, name string, amount int, precision byte, owner, admin, issuer []byte) Asset {
return Asset{}
}
// Renew renews the existence of an asset by the given years. // Renew renews (make available for use) existing asset by the specified number
func Renew(asset Asset, years int) {} // of years. It returns the last block number when this asset will be active.
// It uses `Neo.Asset.Renew` syscall internally.
func Renew(asset Asset, years int) int {
return 0
}

View file

@ -1,17 +1,65 @@
/*
Package attribute provides getters for transaction attributes.
*/
package attribute package attribute
// Package attribute provides function signatures that can be used inside // Attribute represents transaction attribute in Neo, it's an opaque data
// smart contracts that are written in the neo-go framework. // structure that you can get data from only using functions from this package.
// It's similar in function to the TransactionAttribute class in the Neo .net
// Attribute stubs a NEO transaction attribute type. // framework. To use it you need to get is first using transaction.GetAttributes.
type Attribute struct{} type Attribute struct{}
// GetUsage returns the usage of the given attribute. // GetUsage returns the Usage field of the given attribute. It is an enumeration
// with the following possible values:
// ContractHash = 0x00
// ECDH02 = 0x02
// ECDH03 = 0x03
// Script = 0x20
// Vote = 0x30
// CertURL = 0x80
// DescriptionURL = 0x81
// Description = 0x90
//
// Hash1 = 0xa1
// Hash2 = 0xa2
// Hash3 = 0xa3
// Hash4 = 0xa4
// Hash5 = 0xa5
// Hash6 = 0xa6
// Hash7 = 0xa7
// Hash8 = 0xa8
// Hash9 = 0xa9
// Hash10 = 0xaa
// Hash11 = 0xab
// Hash12 = 0xac
// Hash13 = 0xad
// Hash14 = 0xae
// Hash15 = 0xaf
//
// Remark = 0xf0
// Remark1 = 0xf1
// Remark2 = 0xf2
// Remark3 = 0xf3
// Remark4 = 0xf4
// Remark5 = 0xf5
// Remark6 = 0xf6
// Remark7 = 0xf7
// Remark8 = 0xf8
// Remark9 = 0xf9
// Remark10 = 0xfa
// Remark11 = 0xfb
// Remark12 = 0xfc
// Remark13 = 0xfd
// Remark14 = 0xfe
// Remark15 = 0xff
// This function uses `Neo.Attribute.GetUsage` syscall internally.
func GetUsage(attr Attribute) byte { func GetUsage(attr Attribute) byte {
return 0x00 return 0x00
} }
// GetData returns the data of the given attribute. // GetData returns the data of the given attribute, exact interpretation of this
// data depends on attribute's Usage type. It uses `Neo.Attribute.GetData`
// syscall internally.
func GetData(attr Attribute) []byte { func GetData(attr Attribute) []byte {
return nil return nil
} }

View file

@ -1,25 +1,30 @@
/*
Package block provides getters for Neo Block structure.
*/
package block package block
import "github.com/nspcc-dev/neo-go/pkg/interop/transaction" import "github.com/nspcc-dev/neo-go/pkg/interop/transaction"
// Package block provides function signatures that can be used inside // Block represents a NEO block, it's an opaque data structure that you can get
// smart contracts that are written in the neo-go framework. // data from only using functions from this package. It's similar in function to
// the Block class in the Neo .net framework. To use it you need to get it via
// Block stubs a NEO block type. // blockchain.GetBlock function call.
type Block struct{} type Block struct{}
// GetTransactionCount returns the number of recorded transactions in the given block. // GetTransactionCount returns the number of recorded transactions in the given
// block. It uses `Neo.Block.GetTransactionCount` syscall internally.
func GetTransactionCount(b Block) int { func GetTransactionCount(b Block) int {
return 0 return 0
} }
// GetTransactions returns a slice of transactions recorded in the given block. // GetTransactions returns a slice of transactions recorded in the given block.
// It uses `Neo.Block.GetTransactions` syscall internally.
func GetTransactions(b Block) []transaction.Transaction { func GetTransactions(b Block) []transaction.Transaction {
return []transaction.Transaction{} return []transaction.Transaction{}
} }
// GetTransaction returns a transaction from the given a block hash of the // GetTransaction returns transaction from the given block by its index. It
// transaction. // uses `Neo.Block.GetTransaction` syscall internally.
func GetTransaction(b Block, hash []byte) transaction.Transaction { func GetTransaction(b Block, index int) transaction.Transaction {
return transaction.Transaction{} return transaction.Transaction{}
} }

View file

@ -1,3 +1,6 @@
/*
Package blockchain provides functions to access various blockchain data.
*/
package blockchain package blockchain
import ( import (
@ -9,45 +12,72 @@ import (
"github.com/nspcc-dev/neo-go/pkg/interop/transaction" "github.com/nspcc-dev/neo-go/pkg/interop/transaction"
) )
// Package blockchain provides function signatures that can be used inside // GetHeight returns current block height (index of the last accepted block).
// smart contracts that are written in the neo-go framework. // Note that when transaction is being run as a part of new block this block is
// considered as not yet accepted (persisted) and thus you'll get an index of
// GetHeight returns the height of te block recorded in the current execution scope. // the previous (already accepted) block. This function uses
// `Neo.Blockchain.GetHeight` syscall.
func GetHeight() int { func GetHeight() int {
return 0 return 0
} }
// GetHeader returns the header found by the given hash or index. // GetHeader returns header found by the given hash (256 bit hash in BE format
// represented as a slice of 32 bytes) or index (integer). Refer to the `header`
// package for possible uses of returned structure. This function uses
// `Neo.Blockchain.GetHeader` syscall.
func GetHeader(heightOrHash interface{}) header.Header { func GetHeader(heightOrHash interface{}) header.Header {
return header.Header{} return header.Header{}
} }
// GetBlock returns the block found by the given hash or index. // GetBlock returns block found by the given hash or index (with the same
// encoding as for GetHeader). Refer to the `block` package for possible uses
// of returned structure. This function uses `Neo.Blockchain.GetBlock` syscall.
func GetBlock(heightOrHash interface{}) block.Block { func GetBlock(heightOrHash interface{}) block.Block {
return block.Block{} return block.Block{}
} }
// GetTransaction returns the transaction found by the given hash. // GetTransaction returns transaction found by the given (256 bit in BE format
// represented as a slice of 32 bytes). Refer to the `transaction` package for
// possible uses of returned structure. This function uses
// `Neo.Blockchain.GetTransaction` syscall.
func GetTransaction(hash []byte) transaction.Transaction { func GetTransaction(hash []byte) transaction.Transaction {
return transaction.Transaction{} return transaction.Transaction{}
} }
// GetContract returns the contract found by the given script hash. // GetTransactionHeight returns transaction's height (index of the block that
// includes it) by the given ID (256 bit in BE format represented as a slice of
// 32 bytes). This function uses `Neo.Blockchain.GetTransactionHeight` syscall.
func GetTransactionHeight(hash []byte) int {
return 0
}
// GetContract returns contract found by the given script hash (160 bit in BE
// format represented as a slice of 20 bytes). Refer to the `contract` package
// for details on how to use the returned structure. This function uses
// `Neo.Blockchain.GetContract` syscall.
func GetContract(scriptHash []byte) contract.Contract { func GetContract(scriptHash []byte) contract.Contract {
return contract.Contract{} return contract.Contract{}
} }
// GetAccount returns the account found by the given script hash. // GetAccount returns account found by the given script hash (160 bit in BE
// format represented as a slice of 20 bytes). Refer to the `account` package
// for details on how to use the returned structure. This function uses
// `Neo.Blockchain.GetAccount` syscall.
func GetAccount(scriptHash []byte) account.Account { func GetAccount(scriptHash []byte) account.Account {
return account.Account{} return account.Account{}
} }
// GetValidators returns a slice of validator addresses. // GetValidators returns a slice of current validators public keys represented
// as a compressed serialized byte slice (33 bytes long). This function uses
// `Neo.Blockchain.GetValidators` syscall.
func GetValidators() [][]byte { func GetValidators() [][]byte {
return nil return nil
} }
// GetAsset returns the asset found by the given asset id. // GetAsset returns asset found by the given asset ID (256 bit in BE format
// represented as a slice of 32 bytes). Refer to the `asset` package for
// possible uses of returned structure. This function uses
// `Neo.Blockchain.GetAsset` syscall.
func GetAsset(assetID []byte) asset.Asset { func GetAsset(assetID []byte) asset.Asset {
return asset.Asset{} return asset.Asset{}
} }

View file

@ -1,55 +1,85 @@
/*
Package contract provides functions to work with contracts.
*/
package contract package contract
import "github.com/nspcc-dev/neo-go/pkg/interop/storage" import "github.com/nspcc-dev/neo-go/pkg/interop/storage"
// Package contract provides function signatures that can be used inside // Contract represents a Neo contract and is used in interop functions. It's
// smart contracts that are written in the neo-go framework. // an opaque data structure that you can manipulate with using functions from
// this package. It's similar in function to the Contract class in the Neo .net
// Contract stubs a NEO contract type. // framework.
type Contract struct{} type Contract struct{}
// GetScript returns the script of the given contract. // GetScript returns the script of the given contract. It uses
// `Neo.Contract.GetScript` syscall.
func GetScript(c Contract) []byte { func GetScript(c Contract) []byte {
return nil return nil
} }
// IsPayable returns whether the given contract is payable. // IsPayable returns whether the given contract is payable (able to accept
// asset transfers to its address). It uses `Neo.Contract.IsPayable` syscall.
func IsPayable(c Contract) bool { func IsPayable(c Contract) bool {
return false return false
} }
// GetStorageContext returns the storage context for the given contract. // GetStorageContext returns storage context for the given contract. It only
// works for contracts created in this transaction (so you can't take a storage
// context for arbitrary contract). Refer to the `storage` package on how to
// use this context. This function uses `Neo.Contract.GetStorageContext` syscall.
func GetStorageContext(c Contract) storage.Context { func GetStorageContext(c Contract) storage.Context {
return storage.Context{} return storage.Context{}
} }
// Create creates a new contract. // Create creates a new contract using a set of input parameters:
// @FIXME What is the type of the returnType here? // script contract's bytecode (limited in length by 1M)
// params contract's input parameter types, one byte per parameter, see
// ParamType in the `smartcontract` package for value
// definitions. Maximum number of parameters: 252.
// returnType return value type, also a ParamType constant
// properties bit field with contract's permissions (storage, dynamic
// invoke, payable), see PropertyState in the `smartcontract`
// package
// name human-readable contract name (no longer than 252 bytes)
// version human-readable contract version (no longer than 252 bytes)
// author contract's author (no longer than 252 bytes)
// email contract's author/support e-mail (no longer than 252 bytes)
// description human-readable contract description (no longer than 64K bytes)
// It returns this new created Contract when successful (and fails transaction
// if not). It uses `Neo.Contract.Create` syscall.
func Create( func Create(
script []byte, script []byte,
params []interface{}, params []byte,
returnType byte, returnType byte,
properties interface{}, properties byte,
name, name,
version, version,
author, author,
email, email,
description string) { description string) Contract {
return Contract{}
} }
// Migrate migrates a new contract. // Migrate migrates calling contract (that is the one that calls Migrate) to
// @FIXME What is the type of the returnType here? // the new contract. Its parameters have exactly the same semantics as for
// Create. The old contract will be deleted by this call, if it has any storage
// associated it will be migrated to the new contract. New contract is returned.
// This function uses `Neo.Contract.Migrate` syscall.
func Migrate( func Migrate(
script []byte, script []byte,
params []interface{}, params []byte,
returnType byte, returnType byte,
properties interface{}, properties byte,
name, name,
version, version,
author, author,
email, email,
description string) { description string) Contract {
return Contract{}
} }
// Destroy deletes a contract that is registered on the blockchain. // Destroy deletes calling contract (the one that calls Destroy) from the
func Destroy(c Contract) {} // blockchain, so it's only possible to do that from the contract itself and
// not by any outside code. When contract is deleted all associated storage
// items are deleted too. This function uses `Neo.Contract.Destroy` syscall.
func Destroy() {}

View file

@ -1,29 +1,32 @@
/*
Package crypto provides an interface to VM cryptographic instructions.
*/
package crypto package crypto
// Package crypto provides function signatures that can be used inside // SHA1 computes SHA1 hash of b. It uses `SHA1` VM instruction.
// smart contracts that are written in the neo-go framework.
// SHA1 computes the sha1 hash of b.
func SHA1(b []byte) []byte { func SHA1(b []byte) []byte {
return nil return nil
} }
// SHA256 computes the sha256 hash of b. // SHA256 computes SHA256 hash of b. It uses `SHA256` VM instruction.
func SHA256(b []byte) []byte { func SHA256(b []byte) []byte {
return nil return nil
} }
// Hash160 computes the sha256 + ripemd160 of b. // Hash160 computes SHA256 + RIPEMD-160 of b, which is commonly used for
// script hashing and address generation. It uses `HASH160` VM instruction.
func Hash160(b []byte) []byte { func Hash160(b []byte) []byte {
return nil return nil
} }
// Hash256 computes the sha256^2 hash of b. // Hash256 computes double SHA256 hash of b (SHA256(SHA256(b))) which is used
// as ID for transactions, blocks and assets. It uses `HASH256` VM instruction.
func Hash256(b []byte) []byte { func Hash256(b []byte) []byte {
return nil return nil
} }
// VerifySignature checks that sig is msg's signature with pub. // VerifySignature checks that sig is correct msg's signature for a given pub
// (serialized public key). It uses `VERIFY` VM instruction.
func VerifySignature(msg []byte, sig []byte, pub []byte) bool { func VerifySignature(msg []byte, sig []byte, pub []byte) bool {
return false return false
} }

14
pkg/interop/doc.go Normal file
View file

@ -0,0 +1,14 @@
/*
Package interop contains smart contract API functions.
Its subpackages can be imported into smart contracts written in Go to provide
various functionality. Upon compilation, functions from these packages will
be substituted with appropriate NeoVM system calls implemented by Neo. Usually
these system calls have additional price in NeoVM, so they're explicitly written
in the documentation of respective functions.
Note that unless written otherwise structures defined in this packages can't be
correctly created by new() or composite literals, they should be received from
some interop functions (and then used as parameters for some other interop
functions).
*/
package interop

View file

@ -1,34 +1,66 @@
/*
Package engine provides access to VM execution metadata and allows to make contract calls.
It's roughly similar in function to ExecutionEngine class in the Neo .net
framework.
*/
package engine package engine
import "github.com/nspcc-dev/neo-go/pkg/interop/transaction" import "github.com/nspcc-dev/neo-go/pkg/interop/transaction"
// Package engine provides function signatures that can be used inside // GetScriptContainer returns the transaction that initially triggered current
// smart contracts that are written in the neo-go framework. // execution context. It never changes in a single execution, no matter how deep
// this execution goes. See `transaction` package for details on how to use the
// GetScriptContainer returns the transaction that is in the execution context. // returned value. This function uses `System.ExecutionEngine.GetScriptContainer`
// syscall.
func GetScriptContainer() transaction.Transaction { func GetScriptContainer() transaction.Transaction {
return transaction.Transaction{} return transaction.Transaction{}
} }
// GetExecutingScriptHash returns the script hash of the contract that is // GetExecutingScriptHash returns script hash (160 bit in BE form represented
// currently being executed. // as 20-byte slice) of the contract that is currently being executed. Any
// AppCall can change the value returned by this function if it calls a
// different contract. This function uses
// `System.ExecutionEngine.GetExecutingScriptHash` syscall.
func GetExecutingScriptHash() []byte { func GetExecutingScriptHash() []byte {
return nil return nil
} }
// GetCallingScriptHash returns the script hash of the contract that started // GetCallingScriptHash returns script hash (160 bit in BE form represented
// the execution of the current script. // as 20-byte slice) of the contract that started the execution of the currently
// running context (caller of current contract or function), so it's one level
// above the GetExecutingScriptHash in the call stack. It uses
// `System.ExecutionEngine.GetCallingScriptHash` syscall.
func GetCallingScriptHash() []byte { func GetCallingScriptHash() []byte {
return nil return nil
} }
// GetEntryScriptHash returns the script hash of the contract that started the // GetEntryScriptHash returns script hash (160 bit in BE form represented
// execution from the start. // as 20-byte slice) of the contract that initially started current execution
// (this is a script that is contained in a transaction returned by
// GetScriptContainer) execution from the start. This function uses
// `System.ExecutionEngine.GetEntryScriptHash` syscall.
func GetEntryScriptHash() []byte { func GetEntryScriptHash() []byte {
return nil return nil
} }
// AppCall executes script with specified hash using provided arguments. // AppCall executes previously deployed blockchain contract with specified hash
// (160 bit in BE form represented as 20-byte slice) using provided arguments.
// It returns whatever this contract returns. Even though this function accepts
// a slice for scriptHash you can only use it for contracts known at
// compile time, because there is a significant difference between static and
// dynamic calls in Neo (contracts should have a special property declared
// and paid for to be able to use dynamic calls). This function uses `APPCALL`
// opcode.
func AppCall(scriptHash []byte, args ...interface{}) interface{} { func AppCall(scriptHash []byte, args ...interface{}) interface{} {
return nil return nil
} }
// DynAppCall executes previously deployed blockchain contract with specified
// hash (160 bit in BE form represented as 20-byte slice) using provided
// arguments. It returns whatever this contract returns. It differs from AppCall
// in that you can use it for truly dynamic scriptHash values, but at the same
// time using it requires HasDynamicInvoke property set for a contract doing
// this call. This function uses `APPCALL` opcode.
func DynAppCall(scriptHash []byte, args ...interface{}) interface{} {
return nil
}

View file

@ -1,29 +1,41 @@
/*
Package enumerator provides functions to work with enumerators.
*/
package enumerator package enumerator
// Package enumerator provides function signatures that can be used inside // Enumerator represents NEO enumerator type, it's an opaque data structure
// smart contracts that are written in the neo-go framework. // that can be used with functions from this package. It's similar to more
// widely used Iterator (see `iterator` package), but ranging over arrays
// TODO: Check enumerator use cases and add them to the examples folder. // or structures that have values with no explicit keys.
// Enumerator stubs a NEO enumerator type.
type Enumerator struct{} type Enumerator struct{}
// Create creates a new enumerator from the given items. // Create creates a new enumerator from the given items (slice or structure).
// New enumerator points at index -1 of its items, so the user of it has to
// advance it first with Next. This function uses `Neo.Enumerator.Create`
// syscall.
func Create(items []interface{}) Enumerator { func Create(items []interface{}) Enumerator {
return Enumerator{} return Enumerator{}
} }
// Next returns the next item in the iteration. // Next moves position of the given enumerator by one and returns a bool that
func Next(e Enumerator) interface{} { // tells whether there is a new value present in this new position. If it is,
return nil // you can use Value to get it, if not then there are no more values in this
// enumerator. This function uses `Neo.Enumerator.Next` syscall.
func Next(e Enumerator) bool {
return true
} }
// Value returns the enumerator value. // Value returns current enumerator's item value, it's only valid to call it
// after Next returning true. This function uses `Neo.Enumerator.Value` syscall.
func Value(e Enumerator) interface{} { func Value(e Enumerator) interface{} {
return nil return nil
} }
// Concat concatenates the 2 given enumerators. // Concat concatenates two given enumerators returning one that will range on
// a first and then continue with b. Enumerator positions are not reset for a
// and b, so if any of them was already advanced by Next the resulting
// Enumerator will point at this new position and never go back to previous
// values. This function uses `Neo.Enumerator.Concat` syscall.
func Concat(a, b Enumerator) Enumerator { func Concat(a, b Enumerator) Enumerator {
return Enumerator{} return Enumerator{}
} }

View file

@ -1,47 +1,61 @@
/*
Package header contains functions working with block headers.
*/
package header package header
// Package header provides function signatures that can be used inside // Header represents Neo block header type, it's an opaque data structure that
// smart contracts that are written in the neo-go framework. // can be used by functions from this package. You can create it with
// blockchain.GetHeader. In its function it's similar to the Header class
// Header stubs a NEO block header type. // of the Neo .net framework.
type Header struct{} type Header struct{}
// GetIndex returns the index of the given header. // GetIndex returns the index (height) of the given header. It uses
// `Neo.Header.GetIndex` syscall.
func GetIndex(h Header) int { func GetIndex(h Header) int {
return 0 return 0
} }
// GetHash returns the hash of the given header. // GetHash returns the hash (256-bit BE value packed into 32 byte slice) of the
// given header (which also is a hash of the block). It uses `Neo.Header.GetHash`
// syscall.
func GetHash(h Header) []byte { func GetHash(h Header) []byte {
return nil return nil
} }
// GetPrevHash returns the previous hash of the given header. // GetPrevHash returns the hash (256-bit BE value packed into 32 byte slice) of
// the previous block stored in the given header. It uses `Neo.Header.GetPrevHash`
// syscall.
func GetPrevHash(h Header) []byte { func GetPrevHash(h Header) []byte {
return nil return nil
} }
// GetTimestamp returns the timestamp of the given header. // GetTimestamp returns the timestamp of the given header. It uses
// `Neo.Header.GetTimestamp` syscall.
func GetTimestamp(h Header) int { func GetTimestamp(h Header) int {
return 0 return 0
} }
// GetVersion returns the version of the given header. // GetVersion returns the version of the given header. It uses
// `Neo.Header.GetVersion` syscall.
func GetVersion(h Header) int { func GetVersion(h Header) int {
return 0 return 0
} }
// GetMerkleRoot returns the merkle root of the given header. // GetMerkleRoot returns the Merkle root (256-bit BE value packed into 32 byte
// slice) of the given header. It uses `Neo.Header.GetMerkleRoot` syscall.
func GetMerkleRoot(h Header) []byte { func GetMerkleRoot(h Header) []byte {
return nil return nil
} }
// GetConsensusData returns the consensus data of the given header. // GetConsensusData returns the consensus data (nonce) of the given header.
// It uses `Neo.Header.GetConsensusData` syscall.
func GetConsensusData(h Header) int { func GetConsensusData(h Header) int {
return 0 return 0
} }
// GetNextConsensus returns the next consensus of the given header. // GetNextConsensus returns the next consensus field (verification script hash,
// 160-bit BE value packed into 20 byte slice) of the given header. It uses
// `Neo.Header.GetNextConsensus` syscall.
func GetNextConsensus(h Header) []byte { func GetNextConsensus(h Header) []byte {
return nil return nil
} }

View file

@ -1,17 +1,22 @@
/*
Package input provides functions dealing with transaction inputs.
*/
package input package input
// Package input provides function signatures that can be used inside // Input is an opaque data structure that can only be created by
// smart contracts that are written in the neo-go framework. // transaction.GetInputs and it represents transaction's input. It's similar
// to Neo .net framework's TransactionInput.
// Input stubs the input of a NEO transaction.
type Input struct{} type Input struct{}
// GetHash returns the hash of the given input. // GetHash returns the hash stored in the given input (which also is a
// transaction ID represented as 32 byte slice containing 256 bit BE value).
// It uses `Neo.Input.GetHash` syscall.
func GetHash(in Input) []byte { func GetHash(in Input) []byte {
return nil return nil
} }
// GetIndex returns the index of the given input. // GetIndex returns the index stored in the given input (which is a
// transaction's output number). It uses `Neo.Input.GetIndex` syscall.
func GetIndex(in Input) int { func GetIndex(in Input) int {
return 0 return 0
} }

View file

@ -1,39 +1,63 @@
/*
Package iterator provides functions to work with Neo iterators.
*/
package iterator package iterator
// Package iterator provides function signatures that can be used inside import "github.com/nspcc-dev/neo-go/pkg/interop/enumerator"
// smart contracts that are written in the neo-go framework.
// Iterator stubs a NEO iterator object type. // Iterator represents a Neo iterator, it's an opaque data structure that can
// be properly created by Create or storage.Find. Unlike enumerators, iterators
// range over key-value pairs, so it's convenient to use them for maps. This
// structure is similar in function to Neo .net framework's Iterator.
type Iterator struct{} type Iterator struct{}
// Create creates an iterator from the given items. // Create creates an iterator from the given items (array, struct or map). A new
// iterator is set to point at element -1, so to access its first element you
// need to call Next first. This function uses `Neo.Iterator.Create` syscall.
func Create(items []interface{}) Iterator { func Create(items []interface{}) Iterator {
return Iterator{} return Iterator{}
} }
// Key returns the iterator key. // Concat concatenates two given iterators returning one that will range on
// TODO: Better description for this. // a first and then continue with b. Iterator positions are not reset for a
// and b, so if any of them was already advanced by Next the resulting
// Iterator will point at this new position and never go back to previous
// key-value pairs. This function uses `Neo.Iterator.Concat` syscall.
func Concat(a, b Iterator) Iterator {
return Iterator{}
}
// Key returns iterator's key at current position. It's only valid to call after
// successful Next call. This function uses `Neo.Iterator.Key` syscall.
func Key(it Iterator) interface{} { func Key(it Iterator) interface{} {
return nil return nil
} }
// Keys returns the iterator keys. // Keys returns Enumerator ranging over keys or the given Iterator. Note that
func Keys(it Iterator) []interface{} { // this Enumerator is actually directly tied to the underlying Iterator, so that
return nil // advancing it with Next will actually advance the Iterator too. This function
// uses `Neo.Iterator.Keys` syscall.
func Keys(it Iterator) enumerator.Enumerator {
return enumerator.Enumerator{}
} }
// Next advances the iterator, return true if it is was successful // Next advances the iterator returning true if it is was successful (and you
// and false otherwise. // can use Key or Value) and false otherwise (and there are no more elements in
// this Iterator). This function uses `Neo.Iterator.Next` syscall.
func Next(it Iterator) bool { func Next(it Iterator) bool {
return true return true
} }
// Value returns the current iterator value. // Value returns iterator's current value. It's only valid to call after
// successful Next call. This function uses `Neo.Iterator.Value` syscall.
func Value(it Iterator) interface{} { func Value(it Iterator) interface{} {
return nil return nil
} }
// Values returns the iterator values. // Values returns Enumerator ranging over values or the given Iterator. Note that
func Values(it Iterator) []interface{} { // this Enumerator is actually directly tied to the underlying Iterator, so that
return nil // advancing it with Next will actually advance the Iterator too. This function
// uses `Neo.Iterator.Values` syscall.
func Values(it Iterator) enumerator.Enumerator {
return enumerator.Enumerator{}
} }

View file

@ -1,22 +1,28 @@
/*
Package output provides functions dealing with transaction outputs.
*/
package output package output
// Package output provides function signatures that can be used inside // Output is an opaque data structure that can only be created by
// smart contracts that are written in the neo-go framework. // transaction.GetOutputs and it represents transaction's output. It's similar
// to Neo .net framework's TransactionOutput.
// Output stubs the output of a NEO transaction.
type Output struct{} type Output struct{}
// GetAssetID returns the asset id of the given output. // GetAssetID returns the asset ID (256 bit BE value in a 32 byte slice) of the
// given output. It uses `Neo.Output.GetAssetId` syscall.
func GetAssetID(out Output) []byte { func GetAssetID(out Output) []byte {
return nil return nil
} }
// GetValue returns the value of the given output. // GetValue returns the value (asset quantity) of the given output. It uses
// `Neo.Output.GetValue` syscall.
func GetValue(out Output) int { func GetValue(out Output) int {
return 0 return 0
} }
// GetScriptHash returns the script hash of the given output. // GetScriptHash returns the script hash (receiver's address represented as
// 20 byte slice containing 160 bit BE value) of the given output. It uses
// `Neo.Output.GetScriptHash` syscall.
func GetScriptHash(out Output) []byte { func GetScriptHash(out Output) []byte {
return nil return nil
} }

View file

@ -1,48 +1,70 @@
/*
Package runtime provides various service functions related to execution environment.
It has similar function to Runtime class in .net framwork for Neo.
*/
package runtime package runtime
// Package runtime provides function signatures that can be used inside // CheckWitness verifies if the given script hash (160-bit BE value in a 20 byte
// smart contracts that are written in the neo-go framework. // slice) or key (compressed serialized 33-byte form) is one of the signers of
// this invocation. It uses `Neo.Runtime.CheckWitness` syscall.
// CheckWitness verifies if the given hash is the invoker of the contract. func CheckWitness(hashOrKey []byte) bool {
func CheckWitness(hash []byte) bool {
return true return true
} }
// Log instucts the VM to log the given message. // Log instructs VM to log the given message. It's mostly used for debugging
// purposes as these messages are not saved anywhere normally and usually are
// only visible in the VM logs. This function uses `Neo.Runtime.Log` syscall.
func Log(message string) {} func Log(message string) {}
// Notify an event to the VM. // Notify sends a notification (collecting all arguments in an array) to the
func Notify(arg ...interface{}) int { // executing environment. Unlike Log it can accept any data and resulting
return 0 // notification is saved in application log. It's intended to be used as a
} // part of contract's API to external systems, these events can be monitored
// from outside and act upon accordingly. This function uses
// `Neo.Runtime.Notify` syscall.
func Notify(arg ...interface{}) {}
// GetTime returns the timestamp of the most recent block. // GetTime returns the timestamp of the most recent block. Note that when running
// script in test mode this would be the last accepted (persisted) block in the
// chain, but when running as a part of the new block the time returned is the
// time of this (currently being processed) block. This function uses
// `Neo.Runtime.GetTime` syscall.
func GetTime() int { func GetTime() int {
return 0 return 0
} }
// GetTrigger returns the smart contract invoke trigger which can be either // GetTrigger returns the smart contract invocation trigger which can be either
// verification or application. // verification or application. It can be used to differentiate running contract
// as a part of verification process from running it as a regular application.
// Some interop functions (especially ones that change the state in any way) are
// not available when running with verification trigger. This function uses
// `Neo.Runtime.GetTrigger` syscall.
func GetTrigger() byte { func GetTrigger() byte {
return 0x00 return 0x00
} }
// Application returns the Application trigger type // Application returns the Application trigger type value to compare with
// GetTrigger return value.
func Application() byte { func Application() byte {
return 0x10 return 0x10
} }
// Verification returns the Verification trigger type // Verification returns the Verification trigger type value to compare with
// GetTrigger return value.
func Verification() byte { func Verification() byte {
return 0x00 return 0x00
} }
// Serialize serializes and item into a bytearray. // Serialize serializes any given item into a byte slice. It works for all
// regular VM types (not ones from interop package) and allows to save them in
// storage or pass into Notify and then Deserialize them on the next run or in
// the external event receiver. It uses `Neo.Runtime.Serialize` syscall.
func Serialize(item interface{}) []byte { func Serialize(item interface{}) []byte {
return nil return nil
} }
// Deserialize an item from a bytearray. // Deserialize unpacks previously serialized value from a byte slice, it's the
// opposite of Serialize. It uses `Neo.Runtime.Deserialize` syscall.
func Deserialize(b []byte) interface{} { func Deserialize(b []byte) interface{} {
return nil return nil
} }

View file

@ -1,24 +1,54 @@
/*
Package storage provides functions to access and modify contract's storage.
Neo storage's model follows simple key-value DB pattern, this storage is a part
of blockchain state, so you can use it between various invocations of the same
contract.
*/
package storage package storage
import "github.com/nspcc-dev/neo-go/pkg/interop/iterator" import "github.com/nspcc-dev/neo-go/pkg/interop/iterator"
// Package storage provides function signatures that can be used inside // Context represents storage context that is mandatory for Put/Get/Delete
// smart contracts that are written in the neo-go framework. // operations. It's an opaque type that can only be created properly by
// GetContext, GetReadOnlyContext or ConvertContextToReadOnly. It's similar
// Context represents the storage context. // to Neo .net framework's StorageContext class.
type Context struct{} type Context struct{}
// GetContext returns the storage context. // ConvertContextToReadOnly returns new context from the given one, but with
// writing capability turned off, so that you could only invoke Get and Find
// using this new Context. If Context is already read-only this function is a
// no-op. It uses `Neo.StorageContext.AsReadOnly` syscall.
func ConvertContextToReadOnly(ctx Context) Context { return Context{} }
// GetContext returns current contract's (that invokes this function) storage
// context. It uses `Neo.Storage.GetContext` syscall.
func GetContext() Context { return Context{} } func GetContext() Context { return Context{} }
// Put value at given key. // GetReadOnlyContext returns current contract's (that invokes this function)
// storage context in read-only mode, you can use this context for Get and Find
// functions, but using it for Put and Delete will fail. It uses
// `Neo.Storage.GetReadOnlyContext` syscall.
func GetReadOnlyContext() Context { return Context{} }
// Put saves given value with given key in the storage using given Context.
// Even though it accepts interface{} for both, you can only pass simple types
// there like string, []byte, int or bool (not structures or slices of more
// complex types). To put more complex types there serialize them first using
// runtime.Serialize. This function uses `Neo.Storage.Put` syscall.
func Put(ctx Context, key interface{}, value interface{}) {} func Put(ctx Context, key interface{}, value interface{}) {}
// Get value matching given key. // Get retrieves value stored for the given key using given Context. See Put
// documentation on possible key and value types. This function uses
// `Neo.Storage.Get` syscall.
func Get(ctx Context, key interface{}) interface{} { return 0 } func Get(ctx Context, key interface{}) interface{} { return 0 }
// Delete key value pair from storage. // Delete removes key-value pair from storage by the given key using given
// Context. See Put documentation on possible key types. This function uses
// `Neo.Storage.Delete` syscall.
func Delete(ctx Context, key interface{}) {} func Delete(ctx Context, key interface{}) {}
// Find returns an iterator.Iterator over the keys that matched the given key. // Find returns an iterator.Iterator over key-value pairs in the given Context
// that match the given key (contain it as a prefix). See Put documentation on
// possible key types and iterator package documentation on how to use the
// returned value. This function uses `Neo.Storage.Find` syscall.
func Find(ctx Context, key interface{}) iterator.Iterator { return iterator.Iterator{} } func Find(ctx Context, key interface{}) iterator.Iterator { return iterator.Iterator{} }

View file

@ -1,50 +1,82 @@
/*
Package transaction provides functions to work with transactions.
*/
package transaction package transaction
import ( import (
"github.com/nspcc-dev/neo-go/pkg/interop/attribute" "github.com/nspcc-dev/neo-go/pkg/interop/attribute"
"github.com/nspcc-dev/neo-go/pkg/interop/input" "github.com/nspcc-dev/neo-go/pkg/interop/input"
"github.com/nspcc-dev/neo-go/pkg/interop/output" "github.com/nspcc-dev/neo-go/pkg/interop/output"
"github.com/nspcc-dev/neo-go/pkg/interop/witness"
) )
// Package transaction provides function signatures that can be used inside // Transaction represents a NEO transaction, it's an opaque data structure
// smart contracts that are written in the neo-go framework. // that can be used with functions from this package. It's similar to
// Transaction class in Neo .net framework.
// Transaction stubs a NEO transaction type.
type Transaction struct{} type Transaction struct{}
// GetHash returns the hash of the given transaction. // GetHash returns the hash (256 bit BE value in a 32 byte slice) of the given
// transaction (which also is its ID). Is uses `Neo.Transaction.GetHash` syscall.
func GetHash(t Transaction) []byte { func GetHash(t Transaction) []byte {
return nil return nil
} }
// GetType returns the type of the given transaction. // GetType returns the type of the given transaction. Possible values:
// MinerTransaction = 0x00
// IssueTransaction = 0x01
// ClaimTransaction = 0x02
// EnrollmentTransaction = 0x20
// RegisterTransaction = 0x40
// ContractTransaction = 0x80
// StateType = 0x90
// AgencyTransaction = 0xb0
// PublishTransaction = 0xd0
// InvocationTransaction = 0xd1
// It uses `Neo.Transaction.GetType` syscall.
func GetType(t Transaction) byte { func GetType(t Transaction) byte {
return 0x00 return 0x00
} }
// GetAttributes returns a slice of attributes for the given transaction. // GetAttributes returns a slice of attributes for agiven transaction. Refer to
// attribute package on how to use them. This function uses
// `Neo.Transaction.GetAttributes` syscall.
func GetAttributes(t Transaction) []attribute.Attribute { func GetAttributes(t Transaction) []attribute.Attribute {
return []attribute.Attribute{} return []attribute.Attribute{}
} }
// GetReferences returns a slice of references for the given transaction. // GetReferences returns a slice of references for a given Transaction. Elements
// FIXME: What is the correct return type for this? // of this slice can be casted to any of input.Input or output.Output, depending
// on which information you're interested in (as reference technically contains
// both input and corresponding output), refer to input and output package on
// how to use them. This function uses `Neo.Transaction.GetReferences` syscall.
func GetReferences(t Transaction) []interface{} { func GetReferences(t Transaction) []interface{} {
return []interface{}{} return []interface{}{}
} }
// GetUnspentCoins returns the unspent coins for the given transaction. // GetInputs returns a slice of inputs of a given Transaction. Refer to input
// FIXME: What is the correct return type for this? // package on how to use them. This function uses `Neo.Transaction.GetInputs`
func GetUnspentCoins(t Transaction) interface{} { // syscall.
return 0
}
// GetInputs returns the inputs of the given transaction.
func GetInputs(t Transaction) []input.Input { func GetInputs(t Transaction) []input.Input {
return []input.Input{} return []input.Input{}
} }
// GetOutputs returns the outputs of the given transaction. // GetOutputs returns a slice of outputs of a given Transaction. Refer to output
// package on how to use them. This function uses `Neo.Transaction.GetOutputs`
// syscall.
func GetOutputs(t Transaction) []output.Output { func GetOutputs(t Transaction) []output.Output {
return []output.Output{} return []output.Output{}
} }
// GetScript returns the script stored in a given Invocation transaction.
// Calling it for any other Transaction type would lead to failure. It uses
// `Neo.InvocationTransaction.GetScript` syscall.
func GetScript(t Transaction) []byte {
return nil
}
// GetWitnesses returns a slice of witnesses of a given Transaction. Refer to
// witness package on how to use them. This function uses
// `Neo.Transaction.GetWitnesses` syscall.
func GetWitnesses(t Transaction) []witness.Witness {
return []witness.Witness{}
}

View file

@ -1,12 +1,19 @@
/*
Package util contains some special useful functions that are provided by compiler and VM.
*/
package util package util
// FromAddress is an utility function that converts an NEO address to its hash. // FromAddress is an utility function that converts a Neo address to its hash
// (160 bit BE value in a 20 byte slice). It can only be used for strings known
// at compilation time, because the convertion is actually being done by the
// compiler.
func FromAddress(address string) []byte { func FromAddress(address string) []byte {
return nil return nil
} }
// Equals compares a with b and will return true whether a and b // Equals compares a with b and will return true when a and b are equal. It's
// are equal. // implemented as an EQUAL VM opcode, so the rules of comparison are those
// of EQUAL.
func Equals(a, b interface{}) bool { func Equals(a, b interface{}) bool {
return false return false
} }

View file

@ -0,0 +1,14 @@
/*
Package witness provides functions dealing with transaction's witnesses.
*/
package witness
// Witness is an opaque data structure that can only be created by
// transaction.GetWitnesses and representing transaction's witness.
type Witness struct{}
// GetVerificationScript returns verification script stored in the given
// witness. It uses `Neo.Witness.GetVerificationScript` syscall.
func GetVerificationScript(w Witness) []byte {
return nil
}