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
chains/
chain/
blockchain/
blockchains/
# patch
*.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
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.
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

View file

@ -2,66 +2,39 @@
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
* 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
- 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 +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
```
### Debugging your smart contract
### Debugging
You can dump the opcodes generated by the compiler with the following command:
```
@ -112,33 +85,89 @@ INDEX OPCODE DESC
25 0x66 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

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` |
| `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
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 |
| `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`
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.
#### Websocket server
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

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",
"VerifySignature", "AppCall",
"FromAddress", "Equals",
"panic",
"panic", "DynAppCall",
}
)

View file

@ -1085,15 +1085,24 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) {
emit.Opcode(c.prog.BinWriter, opcode.HASH160)
case "VerifySignature":
emit.Opcode(c.prog.BinWriter, opcode.VERIFY)
case "AppCall":
numArgs := len(expr.Args) - 1
case "AppCall", "DynAppCall":
numArgs := len(expr.Args)
if name == "AppCall" {
numArgs--
}
c.emitReverse(numArgs)
emit.Opcode(c.prog.BinWriter, opcode.APPCALL)
buf := c.getByteArray(expr.Args[0])
var buf []byte
if name == "AppCall" {
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)
case "Equals":

View file

@ -9,6 +9,7 @@ import (
"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/util"
"github.com/nspcc-dev/neo-go/pkg/vm"
"github.com/stretchr/testify/require"
)
@ -52,6 +53,19 @@ func TestFromAddress(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 := `
package foo
func Main(a []byte, b []byte) []byte {
@ -62,14 +76,31 @@ func TestAppCall(t *testing.T) {
inner, err := compiler.Compile(strings.NewReader(srcInner))
require.NoError(t, err)
dynapp, err := compiler.Compile(strings.NewReader(srcDynApp))
require.NoError(t, err)
ih := hash.Hash160(inner)
dh := hash.Hash160(dynapp)
getScript := func(u util.Uint160) ([]byte, bool) {
if u.Equals(ih) {
return inner, true
}
if u.Equals(dh) {
return dynapp, hasDynamicInvoke
}
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) {
src := getAppCallScript(fmt.Sprintf("%#v", ih.BytesBE()))
v := vmAndCompile(t, src)
@ -118,6 +149,38 @@ func TestAppCall(t *testing.T) {
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 {

View file

@ -1,12 +1,30 @@
package compiler
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": {
"GetContext": "Neo.Storage.GetContext",
"Put": "Neo.Storage.Put",
"Get": "Neo.Storage.Get",
"ConvertContextToReadOnly": "Neo.StorageContext.AsReadOnly",
"Delete": "Neo.Storage.Delete",
"Find": "Neo.Storage.Find",
"Get": "Neo.Storage.Get",
"GetContext": "Neo.Storage.GetContext",
"GetReadOnlyContext": "Neo.Storage.GetReadOnlyContext",
"Put": "Neo.Storage.Put",
},
"runtime": {
"GetTrigger": "Neo.Runtime.GetTrigger",
@ -18,14 +36,15 @@ var syscalls = map[string]map[string]string{
"Deserialize": "Neo.Runtime.Deserialize",
},
"blockchain": {
"GetHeight": "Neo.Blockchain.GetHeight",
"GetHeader": "Neo.Blockchain.GetHeader",
"GetBlock": "Neo.Blockchain.GetBlock",
"GetTransaction": "Neo.Blockchain.GetTransaction",
"GetContract": "Neo.Blockchain.GetContract",
"GetAccount": "Neo.Blockchain.GetAccount",
"GetValidators": "Neo.Blockchain.GetValidators",
"GetAsset": "Neo.Blockchain.GetAsset",
"GetBlock": "Neo.Blockchain.GetBlock",
"GetContract": "Neo.Blockchain.GetContract",
"GetHeader": "Neo.Blockchain.GetHeader",
"GetHeight": "Neo.Blockchain.GetHeight",
"GetTransaction": "Neo.Blockchain.GetTransaction",
"GetTransactionHeight": "Neo.Blockchain.GetTransactionHeight",
"GetValidators": "Neo.Blockchain.GetValidators",
},
"header": {
"GetIndex": "Neo.Header.GetIndex",
@ -43,20 +62,25 @@ var syscalls = map[string]map[string]string{
"GetTransaction": "Neo.Block.GetTransaction",
},
"transaction": {
"GetHash": "Neo.Transaction.GetHash",
"GetType": "Neo.Transaction.GetType",
"GetAttributes": "Neo.Transaction.GetAttributes",
"GetHash": "Neo.Transaction.GetHash",
"GetInputs": "Neo.Transaction.GetInputs",
"GetOutputs": "Neo.Transaction.GetOutputs",
"GetReferences": "Neo.Transaction.GetReferences",
"GetUnspentCoins": "Neo.Transaction.GetUnspentCoins",
"GetScript": "Neo.Transaction.GetScript",
"GetScript": "Neo.InvocationTransaction.GetScript",
"GetType": "Neo.Transaction.GetType",
"GetWitnesses": "Neo.Transaction.GetWitnesses",
},
"asset": {
"Create": "Neo.Asset.Create",
"GetAdmin": "Neo.Asset.GetAdmin",
"GetAmount": "Neo.Asset.GetAmount",
"GetAssetID": "Neo.Asset.GetAssetID",
"GetAssetType": "Neo.Asset.GetAssetType",
"GetAmount": "Neo.Asset.GetAmount",
"Create": "Neo.Asset.Create",
"GetAvailable": "Neo.Asset.GetAvailable",
"GetIssuer": "Neo.Asset.GetIssuer",
"GetOwner": "Neo.Asset.GetOwner",
"GetPrecision": "Neo.Asset.GetPrecision",
"Renew": "Neo.Asset.Renew",
},
"contract": {
@ -83,6 +107,7 @@ var syscalls = map[string]map[string]string{
"GetExecutingScriptHash": "System.ExecutionEngine.GetExecutingScriptHash",
},
"iterator": {
"Concat": "Neo.Iterator.Concat",
"Create": "Neo.Iterator.Create",
"Key": "Neo.Iterator.Key",
"Keys": "Neo.Iterator.Keys",
@ -90,4 +115,7 @@ var syscalls = map[string]map[string]string{
"Value": "Neo.Iterator.Value",
"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.
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)
return nil
}

View file

@ -575,8 +575,12 @@ func (ic *interopContext) contractGetStorageContext(v *vm.VM) error {
if !ok {
return fmt.Errorf("%T is not a contract state", cs)
}
contractState, err := ic.dao.GetContractState(cs.ScriptHash())
if contractState == nil || err != nil {
_, err := ic.dao.GetContractState(cs.ScriptHash())
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")
}
stc := &StorageContext{

View file

@ -27,6 +27,7 @@ type interopContext struct {
block *block.Block
tx *transaction.Transaction
dao *dao.Cached
lowerDao dao.DAO
notifications []state.NotificationEvent
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 {
dao := dao.NewCached(d)
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

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 provides function signatures that can be used inside
// smart contracts that are written in the neo-go framework.
// Account stubs a NEO account type.
// Account represents NEO account type that is used in interop functions, it's
// 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
// framework.
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 {
return nil
}
// GetVotes returns the votes of the given account which should be a slice of
// public key raw bytes.
// GetVotes returns current votes of the given account represented as a slice of
// 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 {
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 {
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 provides function signatures that can be used inside
// smart contracts that are written in the neo-go framework.
// Asset stubs a NEO asset type.
// Asset represents NEO asset type that is used in interop functions, it's
// 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
// 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{}
// 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 {
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 {
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 {
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 {
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 {
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 {
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 {
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 {
return nil
}
// Create registers a new asset on the blockchain.
func Create(assetType byte, name string, amount int, precision byte, owner, admin, issuer []byte) {}
// Create registers a new asset on the blockchain (similar to old Register
// 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.
func Renew(asset Asset, years int) {}
// Renew renews (make available for use) existing asset by the specified number
// 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 provides function signatures that can be used inside
// smart contracts that are written in the neo-go framework.
// Attribute stubs a NEO transaction attribute type.
// Attribute represents transaction attribute in Neo, it's an opaque data
// 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
// framework. To use it you need to get is first using transaction.GetAttributes.
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 {
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 {
return nil
}

View file

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

View file

@ -1,3 +1,6 @@
/*
Package blockchain provides functions to access various blockchain data.
*/
package blockchain
import (
@ -9,45 +12,72 @@ import (
"github.com/nspcc-dev/neo-go/pkg/interop/transaction"
)
// Package blockchain provides function signatures that can be used inside
// smart contracts that are written in the neo-go framework.
// GetHeight returns the height of te block recorded in the current execution scope.
// GetHeight returns current block height (index of the last accepted block).
// 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
// the previous (already accepted) block. This function uses
// `Neo.Blockchain.GetHeight` syscall.
func GetHeight() int {
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 {
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 {
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 {
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 {
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 {
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 {
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 {
return asset.Asset{}
}

View file

@ -1,55 +1,85 @@
/*
Package contract provides functions to work with contracts.
*/
package contract
import "github.com/nspcc-dev/neo-go/pkg/interop/storage"
// Package contract provides function signatures that can be used inside
// smart contracts that are written in the neo-go framework.
// Contract stubs a NEO contract type.
// Contract represents a Neo contract and is used in interop functions. It's
// 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
// framework.
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 {
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 {
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 {
return storage.Context{}
}
// Create creates a new contract.
// @FIXME What is the type of the returnType here?
// Create creates a new contract using a set of input parameters:
// 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(
script []byte,
params []interface{},
params []byte,
returnType byte,
properties interface{},
properties byte,
name,
version,
author,
email,
description string) {
description string) Contract {
return Contract{}
}
// Migrate migrates a new contract.
// @FIXME What is the type of the returnType here?
// Migrate migrates calling contract (that is the one that calls Migrate) to
// 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(
script []byte,
params []interface{},
params []byte,
returnType byte,
properties interface{},
properties byte,
name,
version,
author,
email,
description string) {
description string) Contract {
return Contract{}
}
// Destroy deletes a contract that is registered on the blockchain.
func Destroy(c Contract) {}
// Destroy deletes calling contract (the one that calls Destroy) from the
// 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 provides function signatures that can be used inside
// smart contracts that are written in the neo-go framework.
// SHA1 computes the sha1 hash of b.
// SHA1 computes SHA1 hash of b. It uses `SHA1` VM instruction.
func SHA1(b []byte) []byte {
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 {
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 {
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 {
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 {
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
import "github.com/nspcc-dev/neo-go/pkg/interop/transaction"
// Package engine provides function signatures that can be used inside
// smart contracts that are written in the neo-go framework.
// GetScriptContainer returns the transaction that is in the execution context.
// GetScriptContainer returns the transaction that initially triggered current
// 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
// returned value. This function uses `System.ExecutionEngine.GetScriptContainer`
// syscall.
func GetScriptContainer() transaction.Transaction {
return transaction.Transaction{}
}
// GetExecutingScriptHash returns the script hash of the contract that is
// currently being executed.
// GetExecutingScriptHash returns script hash (160 bit in BE form represented
// 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 {
return nil
}
// GetCallingScriptHash returns the script hash of the contract that started
// the execution of the current script.
// GetCallingScriptHash returns script hash (160 bit in BE form represented
// 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 {
return nil
}
// GetEntryScriptHash returns the script hash of the contract that started the
// execution from the start.
// GetEntryScriptHash returns script hash (160 bit in BE form represented
// 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 {
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{} {
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 provides function signatures that can be used inside
// smart contracts that are written in the neo-go framework.
// TODO: Check enumerator use cases and add them to the examples folder.
// Enumerator stubs a NEO enumerator type.
// Enumerator represents NEO enumerator type, it's an opaque data structure
// that can be used with functions from this package. It's similar to more
// widely used Iterator (see `iterator` package), but ranging over arrays
// or structures that have values with no explicit keys.
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 {
return Enumerator{}
}
// Next returns the next item in the iteration.
func Next(e Enumerator) interface{} {
return nil
// Next moves position of the given enumerator by one and returns a bool that
// tells whether there is a new value present in this new position. If it is,
// 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{} {
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 {
return Enumerator{}
}

View file

@ -1,47 +1,61 @@
/*
Package header contains functions working with block headers.
*/
package header
// Package header provides function signatures that can be used inside
// smart contracts that are written in the neo-go framework.
// Header stubs a NEO block header type.
// Header represents Neo block header type, it's an opaque data structure that
// 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
// of the Neo .net framework.
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 {
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 {
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 {
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 {
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 {
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 {
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 {
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 {
return nil
}

View file

@ -1,17 +1,22 @@
/*
Package input provides functions dealing with transaction inputs.
*/
package input
// Package input provides function signatures that can be used inside
// smart contracts that are written in the neo-go framework.
// Input stubs the input of a NEO transaction.
// Input is an opaque data structure that can only be created by
// transaction.GetInputs and it represents transaction's input. It's similar
// to Neo .net framework's TransactionInput.
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 {
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 {
return 0
}

View file

@ -1,39 +1,63 @@
/*
Package iterator provides functions to work with Neo iterators.
*/
package iterator
// Package iterator provides function signatures that can be used inside
// smart contracts that are written in the neo-go framework.
import "github.com/nspcc-dev/neo-go/pkg/interop/enumerator"
// 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{}
// 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 {
return Iterator{}
}
// Key returns the iterator key.
// TODO: Better description for this.
// Concat concatenates two given iterators returning one that will range on
// 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{} {
return nil
}
// Keys returns the iterator keys.
func Keys(it Iterator) []interface{} {
return nil
// Keys returns Enumerator ranging over keys or the given Iterator. Note that
// this Enumerator is actually directly tied to the underlying Iterator, so that
// 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
// and false otherwise.
// Next advances the iterator returning true if it is was successful (and you
// 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 {
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{} {
return nil
}
// Values returns the iterator values.
func Values(it Iterator) []interface{} {
return nil
// Values returns Enumerator ranging over values or the given Iterator. Note that
// this Enumerator is actually directly tied to the underlying Iterator, so that
// 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 provides function signatures that can be used inside
// smart contracts that are written in the neo-go framework.
// Output stubs the output of a NEO transaction.
// Output is an opaque data structure that can only be created by
// transaction.GetOutputs and it represents transaction's output. It's similar
// to Neo .net framework's TransactionOutput.
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 {
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 {
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 {
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 provides function signatures that can be used inside
// smart contracts that are written in the neo-go framework.
// CheckWitness verifies if the given hash is the invoker of the contract.
func CheckWitness(hash []byte) bool {
// CheckWitness verifies if the given script hash (160-bit BE value in a 20 byte
// slice) or key (compressed serialized 33-byte form) is one of the signers of
// this invocation. It uses `Neo.Runtime.CheckWitness` syscall.
func CheckWitness(hashOrKey []byte) bool {
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) {}
// Notify an event to the VM.
func Notify(arg ...interface{}) int {
return 0
}
// Notify sends a notification (collecting all arguments in an array) to the
// executing environment. Unlike Log it can accept any data and resulting
// 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 {
return 0
}
// GetTrigger returns the smart contract invoke trigger which can be either
// verification or application.
// GetTrigger returns the smart contract invocation trigger which can be either
// 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 {
return 0x00
}
// Application returns the Application trigger type
// Application returns the Application trigger type value to compare with
// GetTrigger return value.
func Application() byte {
return 0x10
}
// Verification returns the Verification trigger type
// Verification returns the Verification trigger type value to compare with
// GetTrigger return value.
func Verification() byte {
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 {
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{} {
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
import "github.com/nspcc-dev/neo-go/pkg/interop/iterator"
// Package storage provides function signatures that can be used inside
// smart contracts that are written in the neo-go framework.
// Context represents the storage context.
// Context represents storage context that is mandatory for Put/Get/Delete
// operations. It's an opaque type that can only be created properly by
// GetContext, GetReadOnlyContext or ConvertContextToReadOnly. It's similar
// to Neo .net framework's StorageContext class.
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{} }
// 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{}) {}
// 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 }
// 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{}) {}
// 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{} }

View file

@ -1,50 +1,82 @@
/*
Package transaction provides functions to work with transactions.
*/
package transaction
import (
"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/output"
"github.com/nspcc-dev/neo-go/pkg/interop/witness"
)
// Package transaction provides function signatures that can be used inside
// smart contracts that are written in the neo-go framework.
// Transaction stubs a NEO transaction type.
// Transaction represents a NEO transaction, it's an opaque data structure
// that can be used with functions from this package. It's similar to
// Transaction class in Neo .net framework.
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 {
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 {
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 {
return []attribute.Attribute{}
}
// GetReferences returns a slice of references for the given transaction.
// FIXME: What is the correct return type for this?
// GetReferences returns a slice of references for a given Transaction. Elements
// 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{} {
return []interface{}{}
}
// GetUnspentCoins returns the unspent coins for the given transaction.
// FIXME: What is the correct return type for this?
func GetUnspentCoins(t Transaction) interface{} {
return 0
}
// GetInputs returns the inputs of the given transaction.
// GetInputs returns a slice of inputs of a given Transaction. Refer to input
// package on how to use them. This function uses `Neo.Transaction.GetInputs`
// syscall.
func GetInputs(t Transaction) []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 {
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
// 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 {
return nil
}
// Equals compares a with b and will return true whether a and b
// are equal.
// Equals compares a with b and will return true when a and b are equal. It's
// implemented as an EQUAL VM opcode, so the rules of comparison are those
// of EQUAL.
func Equals(a, b interface{}) bool {
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
}