forked from TrueCloudLab/neoneo-go
*: apply go 1.19 formatter heuristics
And make manual corrections where needed. See the "Common mistakes and pitfalls" section of https://tip.golang.org/doc/comment.
This commit is contained in:
parent
bb751535d3
commit
916f2293b8
20 changed files with 167 additions and 150 deletions
|
@ -210,12 +210,13 @@ func lastStmtIsReturn(body *ast.BlockStmt) (b bool) {
|
|||
|
||||
// analyzePkgOrder sets the order in which packages should be processed.
|
||||
// From Go spec:
|
||||
// A package with no imports is initialized by assigning initial values to all its package-level variables
|
||||
// followed by calling all init functions in the order they appear in the source, possibly in multiple files,
|
||||
// as presented to the compiler. If a package has imports, the imported packages are initialized before
|
||||
// initializing the package itself. If multiple packages import a package, the imported package
|
||||
// will be initialized only once. The importing of packages, by construction, guarantees
|
||||
// that there can be no cyclic initialization dependencies.
|
||||
//
|
||||
// A package with no imports is initialized by assigning initial values to all its package-level variables
|
||||
// followed by calling all init functions in the order they appear in the source, possibly in multiple files,
|
||||
// as presented to the compiler. If a package has imports, the imported packages are initialized before
|
||||
// initializing the package itself. If multiple packages import a package, the imported package
|
||||
// will be initialized only once. The importing of packages, by construction, guarantees
|
||||
// that there can be no cyclic initialization dependencies.
|
||||
func (c *codegen) analyzePkgOrder() {
|
||||
seen := make(map[string]bool)
|
||||
info := c.buildInfo.program[0]
|
||||
|
|
|
@ -1341,19 +1341,21 @@ func (c *codegen) isCallExprSyscall(e ast.Expr) bool {
|
|||
|
||||
// processDefers emits code for `defer` statements.
|
||||
// TRY-related opcodes handle exception as follows:
|
||||
// 1. CATCH block is executed only if exception has occurred.
|
||||
// 2. FINALLY block is always executed, but after catch block.
|
||||
// 1. CATCH block is executed only if exception has occurred.
|
||||
// 2. FINALLY block is always executed, but after catch block.
|
||||
//
|
||||
// Go `defer` statements are a bit different:
|
||||
// 1. `defer` is always executed irregardless of whether an exception has occurred.
|
||||
// 2. `recover` can or can not handle a possible exception.
|
||||
// 1. `defer` is always executed irregardless of whether an exception has occurred.
|
||||
// 2. `recover` can or can not handle a possible exception.
|
||||
//
|
||||
// Thus, we use the following approach:
|
||||
// 1. Throwed exception is saved in a static field X, static fields Y and it is set to true.
|
||||
// 2. For each defer local there is a dedicated local variable which is set to 1 if `defer` statement
|
||||
// is encountered during an actual execution.
|
||||
// 3. CATCH and FINALLY blocks are the same, and both contain the same CALLs.
|
||||
// 4. Right before the CATCH block, check a variable from (2). If it is null, jump to the end of CATCH+FINALLY block.
|
||||
// 5. In CATCH block we set Y to true and emit default return values if it is the last defer.
|
||||
// 6. Execute FINALLY block only if Y is false.
|
||||
// 1. Throwed exception is saved in a static field X, static fields Y and it is set to true.
|
||||
// 2. For each defer local there is a dedicated local variable which is set to 1 if `defer` statement
|
||||
// is encountered during an actual execution.
|
||||
// 3. CATCH and FINALLY blocks are the same, and both contain the same CALLs.
|
||||
// 4. Right before the CATCH block, check a variable from (2). If it is null, jump to the end of CATCH+FINALLY block.
|
||||
// 5. In CATCH block we set Y to true and emit default return values if it is the last defer.
|
||||
// 6. Execute FINALLY block only if Y is false.
|
||||
func (c *codegen) processDefers() {
|
||||
for i := len(c.scope.deferStack) - 1; i >= 0; i-- {
|
||||
stmt := c.scope.deferStack[i]
|
||||
|
@ -1399,10 +1401,10 @@ func (c *codegen) processDefers() {
|
|||
|
||||
// emitExplicitConvert handles `someType(someValue)` conversions between string/[]byte.
|
||||
// Rules for conversion:
|
||||
// 1. interop.* types are converted to ByteArray if not already.
|
||||
// 2. Otherwise, convert between ByteArray/Buffer.
|
||||
// 3. Rules for types which are not string/[]byte should already
|
||||
// be enforced by go parser.
|
||||
// 1. interop.* types are converted to ByteArray if not already.
|
||||
// 2. Otherwise, convert between ByteArray/Buffer.
|
||||
// 3. Rules for types which are not string/[]byte should already
|
||||
// be enforced by go parser.
|
||||
func (c *codegen) emitExplicitConvert(from, to types.Type) {
|
||||
if isInteropPath(to.String()) {
|
||||
if isByteSlice(from) && !isString(from) {
|
||||
|
@ -1859,10 +1861,10 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) {
|
|||
// transformArgs returns a list of function arguments
|
||||
// which should be put on stack.
|
||||
// There are special cases for builtins:
|
||||
// 1. With FromAddress, parameter conversion is happening at compile-time
|
||||
// so there is no need to push parameters on stack and perform an actual call
|
||||
// 2. With panic, the generated code depends on the fact if an argument was nil or a string;
|
||||
// so, it should be handled accordingly.
|
||||
// 1. With FromAddress, parameter conversion is happening at compile-time
|
||||
// so there is no need to push parameters on stack and perform an actual call
|
||||
// 2. With panic, the generated code depends on the fact if an argument was nil or a string;
|
||||
// so, it should be handled accordingly.
|
||||
func transformArgs(fs *funcScope, fun ast.Expr, args []ast.Expr) []ast.Expr {
|
||||
switch f := fun.(type) {
|
||||
case *ast.SelectorExpr:
|
||||
|
|
|
@ -15,11 +15,12 @@ import (
|
|||
|
||||
// inlineCall inlines call of n for function represented by f.
|
||||
// Call `f(a,b)` for definition `func f(x,y int)` is translated to block:
|
||||
// {
|
||||
// x := a
|
||||
// y := b
|
||||
// <inline body of f directly>
|
||||
// }
|
||||
//
|
||||
// {
|
||||
// x := a
|
||||
// y := b
|
||||
// <inline body of f directly>
|
||||
// }
|
||||
func (c *codegen) inlineCall(f *funcScope, n *ast.CallExpr) {
|
||||
offSz := len(c.inlineContext)
|
||||
c.inlineContext = append(c.inlineContext, inlineContextSingle{
|
||||
|
|
|
@ -32,8 +32,8 @@ var (
|
|||
// TestCreateBasicChain generates "../rpc/testdata/testblocks.acc" file which
|
||||
// contains data for RPC unit tests. It also is a nice integration test.
|
||||
// To generate new "../rpc/testdata/testblocks.acc", follow the steps:
|
||||
// 1. Set saveChain down below to true
|
||||
// 2. Run tests with `$ make test`
|
||||
// 1. Set saveChain down below to true
|
||||
// 2. Run tests with `$ make test`
|
||||
func TestCreateBasicChain(t *testing.T) {
|
||||
const saveChain = false
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
Package core implements Neo ledger functionality.
|
||||
It's built around the Blockchain structure that maintains state of the ledger.
|
||||
|
||||
Events
|
||||
# Events
|
||||
|
||||
You can subscribe to Blockchain events using a set of Subscribe and Unsubscribe
|
||||
methods. These methods accept channels that will be used to send appropriate
|
||||
|
@ -24,6 +24,5 @@ way they're stored in the block.
|
|||
Be careful using these subscriptions, this mechanism is not intended to be used
|
||||
by lots of subscribers and failing to read from event channels can affect
|
||||
other Blockchain operations.
|
||||
|
||||
*/
|
||||
package core
|
||||
|
|
|
@ -21,12 +21,12 @@ var (
|
|||
|
||||
// Billet is a part of an MPT trie with missing hash nodes that need to be restored.
|
||||
// Billet is based on the following assumptions:
|
||||
// 1. Refcount can only be incremented (we don't change the MPT structure during restore,
|
||||
// thus don't need to decrease refcount).
|
||||
// 2. Each time a part of a Billet is completely restored, it is collapsed into
|
||||
// HashNode.
|
||||
// 3. Any pair (node, path) must be restored only once. It's a duty of an MPT pool to manage
|
||||
// MPT paths in order to provide this assumption.
|
||||
// 1. Refcount can only be incremented (we don't change the MPT structure during restore,
|
||||
// thus don't need to decrease refcount).
|
||||
// 2. Each time a part of a Billet is completely restored, it is collapsed into
|
||||
// HashNode.
|
||||
// 3. Any pair (node, path) must be restored only once. It's a duty of an MPT pool to manage
|
||||
// MPT paths in order to provide this assumption.
|
||||
type Billet struct {
|
||||
TempStoragePrefix storage.KeyPrefix
|
||||
Store *storage.MemCachedStore
|
||||
|
|
|
@ -37,15 +37,15 @@ func prepareMPTCompat() *Trie {
|
|||
// TestCompatibility contains tests present in C# implementation.
|
||||
// https://github.com/neo-project/neo-modules/blob/master/tests/Neo.Plugins.StateService.Tests/MPT/UT_MPTTrie.cs
|
||||
// There are some differences, though:
|
||||
// 1. In our implementation, delete is silent, i.e. we do not return an error if the key is missing or empty.
|
||||
// However, we do return an error when the contents of the hash node are missing from the store
|
||||
// (corresponds to exception in C# implementation). However, if the key is too big, an error is returned
|
||||
// (corresponds to exception in C# implementation).
|
||||
// 2. In our implementation, put returns an error if something goes wrong, while C# implementation throws
|
||||
// an exception and returns nothing.
|
||||
// 3. In our implementation, get does not immediately return any error in case of an empty key. An error is returned
|
||||
// only if the value is missing from the storage. C# implementation checks that the key is not empty and throws an error
|
||||
// otherwise. However, if the key is too big, an error is returned (corresponds to exception in C# implementation).
|
||||
// 1. In our implementation, delete is silent, i.e. we do not return an error if the key is missing or empty.
|
||||
// However, we do return an error when the contents of the hash node are missing from the store
|
||||
// (corresponds to exception in C# implementation). However, if the key is too big, an error is returned
|
||||
// (corresponds to exception in C# implementation).
|
||||
// 2. In our implementation, put returns an error if something goes wrong, while C# implementation throws
|
||||
// an exception and returns nothing.
|
||||
// 3. In our implementation, get does not immediately return any error in case of an empty key. An error is returned
|
||||
// only if the value is missing from the storage. C# implementation checks that the key is not empty and throws an error
|
||||
// otherwise. However, if the key is too big, an error is returned (corresponds to exception in C# implementation).
|
||||
func TestCompatibility(t *testing.T) {
|
||||
mainTrie := prepareMPTCompat()
|
||||
|
||||
|
|
|
@ -4,11 +4,11 @@ Package mpt implements MPT (Merkle-Patricia Trie).
|
|||
An MPT stores key-value pairs and is a trie over 16-symbol alphabet. https://en.wikipedia.org/wiki/Trie
|
||||
A trie is a tree where values are stored in leafs and keys are paths from the root to the leaf node.
|
||||
An MPT consists of 4 types of nodes:
|
||||
- Leaf node only contains a value.
|
||||
- Extension node contains both a key and a value.
|
||||
- Branch node contains 2 or more children.
|
||||
- Hash node is a compressed node and only contains the actual node's hash.
|
||||
The actual node must be retrieved from the storage or over the network.
|
||||
- Leaf node only contains a value.
|
||||
- Extension node contains both a key and a value.
|
||||
- Branch node contains 2 or more children.
|
||||
- Hash node is a compressed node and only contains the actual node's hash.
|
||||
The actual node must be retrieved from the storage or over the network.
|
||||
|
||||
As an example here is a trie containing 3 pairs:
|
||||
- 0x1201 -> val1
|
||||
|
@ -16,18 +16,18 @@ As an example here is a trie containing 3 pairs:
|
|||
- 0x1224 -> val3
|
||||
- 0x12 -> val4
|
||||
|
||||
ExtensionNode(0x0102), Next
|
||||
_______________________|
|
||||
|
|
||||
BranchNode [0, 1, 2, ...], Last -> Leaf(val4)
|
||||
| |
|
||||
| ExtensionNode [0x04], Next -> Leaf(val3)
|
||||
|
|
||||
BranchNode [0, 1, 2, 3, ...], Last -> HashNode(nil)
|
||||
| |
|
||||
| Leaf(val2)
|
||||
|
|
||||
Leaf(val1)
|
||||
ExtensionNode(0x0102), Next
|
||||
_______________________|
|
||||
|
|
||||
BranchNode [0, 1, 2, ...], Last -> Leaf(val4)
|
||||
| |
|
||||
| ExtensionNode [0x04], Next -> Leaf(val3)
|
||||
|
|
||||
BranchNode [0, 1, 2, 3, ...], Last -> HashNode(nil)
|
||||
| |
|
||||
| Leaf(val2)
|
||||
|
|
||||
Leaf(val1)
|
||||
|
||||
There are 3 invariants that this implementation has:
|
||||
- Branch node cannot have <= 1 children
|
||||
|
|
|
@ -97,7 +97,8 @@ func getEffectiveSize(buf []byte, isNeg bool) int {
|
|||
|
||||
// ToBytes converts an integer to a slice in little-endian format.
|
||||
// Note: NEO3 serialization differs from default C# BigInteger.ToByteArray()
|
||||
// when n == 0. For zero is equal to empty slice in NEO3.
|
||||
// when n == 0. For zero is equal to empty slice in NEO3.
|
||||
//
|
||||
// https://github.com/neo-project/neo-vm/blob/master/src/neo-vm/Types/Integer.cs#L16
|
||||
func ToBytes(n *big.Int) []byte {
|
||||
return ToPreallocatedBytes(n, []byte{})
|
||||
|
|
|
@ -8,6 +8,7 @@ in the documentation of respective functions.
|
|||
|
||||
Types defined here are used for proper manifest generation. Here is how Go types
|
||||
correspond to smartcontract and VM types:
|
||||
|
||||
int-like - Integer
|
||||
bool - Boolean
|
||||
[]byte - ByteArray (Buffer in VM)
|
||||
|
@ -15,8 +16,9 @@ correspond to smartcontract and VM types:
|
|||
(interface{})(nil) - Any
|
||||
non-byte slice - Array
|
||||
map[K]V - map
|
||||
|
||||
Other types are defined explicitly in this pkg:
|
||||
Hash160, Hash256, Interface, PublicKey, Signature
|
||||
[Hash160], [Hash256], [Interface], [PublicKey], [Signature].
|
||||
|
||||
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
|
||||
|
|
|
@ -35,36 +35,35 @@ const MinimumResponseGas = 10_000_000
|
|||
// Request makes an oracle request. It can only be successfully invoked by
|
||||
// a deployed contract and it takes the following parameters:
|
||||
//
|
||||
// url
|
||||
// URL to fetch, only https and neofs URLs are supported like
|
||||
// https://example.com/some.json or
|
||||
// neofs:6pJtLUnGqDxE2EitZYLsDzsfTDVegD6BrRUn8QAFZWyt/5Cyxb3wrHDw5pqY63hb5otCSsJ24ZfYmsA8NAjtho2gr
|
||||
// - url
|
||||
// URL to fetch, only https and neofs URLs are supported like
|
||||
// https://example.com/some.json or
|
||||
// neofs:6pJtLUnGqDxE2EitZYLsDzsfTDVegD6BrRUn8QAFZWyt/5Cyxb3wrHDw5pqY63hb5otCSsJ24ZfYmsA8NAjtho2gr
|
||||
//
|
||||
// filter
|
||||
// JSONPath filter to process the result; if specified, it will be
|
||||
// applied to the data returned from HTTP/NeoFS and you'll only get
|
||||
// filtered data in your callback method.
|
||||
// - filter
|
||||
// JSONPath filter to process the result; if specified, it will be
|
||||
// applied to the data returned from HTTP/NeoFS and you'll only get
|
||||
// filtered data in your callback method.
|
||||
//
|
||||
// cb
|
||||
// name of the method that will process oracle data, it must be a method
|
||||
// of the same contract that invokes Request and it must have the following
|
||||
// signature for correct invocation:
|
||||
// - cb
|
||||
// name of the method that will process oracle data, it must be a method
|
||||
// of the same contract that invokes Request and it must have the following
|
||||
// signature for correct invocation:
|
||||
//
|
||||
// Method(url string, userData interface{}, code int, result []byte)
|
||||
// - Method(url string, userData interface{}, code int, result []byte)
|
||||
// where url is the same url specified for Request, userData is anything
|
||||
// passed in the next parameter, code is the status of the reply and
|
||||
// result is the data returned from the request if any.
|
||||
//
|
||||
// where url is the same url specified for Request, userData is anything
|
||||
// passed in the next parameter, code is the status of the reply and
|
||||
// result is the data returned from the request if any.
|
||||
// - userData
|
||||
// data to pass to the callback function.
|
||||
//
|
||||
// userData
|
||||
// data to pass to the callback function.
|
||||
//
|
||||
// gasForResponse
|
||||
// GAS attached to this request for reply callback processing,
|
||||
// note that it's different from the oracle request price, this
|
||||
// GAS is used for oracle transaction's network and system fees,
|
||||
// so it should be enough to pay for reply data as well as
|
||||
// its processing.
|
||||
// - gasForResponse
|
||||
// GAS attached to this request for reply callback processing,
|
||||
// note that it's different from the oracle request price, this
|
||||
// GAS is used for oracle transaction's network and system fees,
|
||||
// so it should be enough to pay for reply data as well as
|
||||
// its processing.
|
||||
func Request(url string, filter []byte, cb string, userData interface{}, gasForResponse int) {
|
||||
neogointernal.CallWithTokenNoRet(Hash, "request",
|
||||
int(contract.States|contract.AllowNotify),
|
||||
|
|
|
@ -46,11 +46,12 @@ func JSONSerialize(item interface{}) []byte {
|
|||
// JSONDeserialize deserializes a value from json. It uses `jsonDeserialize` method of StdLib
|
||||
// native contract.
|
||||
// It performs deserialization as follows:
|
||||
// strings -> []byte (string) from base64
|
||||
// integers -> (u)int* types
|
||||
// null -> interface{}(nil)
|
||||
// arrays -> []interface{}
|
||||
// maps -> map[string]interface{}
|
||||
//
|
||||
// strings -> []byte (string) from base64
|
||||
// integers -> (u)int* types
|
||||
// null -> interface{}(nil)
|
||||
// arrays -> []interface{}
|
||||
// maps -> map[string]interface{}
|
||||
func JSONDeserialize(data []byte) interface{} {
|
||||
return neogointernal.CallWithToken(Hash, "jsonDeserialize", int(contract.NoneFlag),
|
||||
data)
|
||||
|
|
|
@ -4,12 +4,13 @@ It can be used to implement unit-tests for contracts in Go using regular Go
|
|||
conventions.
|
||||
|
||||
Usually it's used like this:
|
||||
* an instance of the blockchain is created using chain subpackage
|
||||
* the target contract is compiled using one of Compile* functions
|
||||
* and Executor is created for the blockchain
|
||||
* it's used to deploy a contract with DeployContract
|
||||
* CommitteeInvoker and/or ValidatorInvoker are then created to perform test invocations
|
||||
* if needed, NewAccount is used to create an appropriate number of accounts for the test
|
||||
|
||||
- an instance of the blockchain is created using chain subpackage
|
||||
- the target contract is compiled using one of Compile* functions
|
||||
- and Executor is created for the blockchain
|
||||
- it's used to deploy a contract with DeployContract
|
||||
- CommitteeInvoker and/or ValidatorInvoker are then created to perform test invocations
|
||||
- if needed, NewAccount is used to create an appropriate number of accounts for the test
|
||||
|
||||
Higher-order methods provided in Executor and ContractInvoker hide the details
|
||||
of transaction creation for the most part, but there are lower-level methods as
|
||||
|
|
|
@ -1123,9 +1123,10 @@ func (s *Server) handleGetAddrCmd(p Peer) error {
|
|||
// requestBlocks sends a CMDGetBlockByIndex message to the peer
|
||||
// to sync up in blocks. A maximum of maxBlockBatch will be
|
||||
// sent at once. There are two things we need to take care of:
|
||||
// 1. If possible, blocks should be fetched in parallel.
|
||||
// height..+500 to one peer, height+500..+1000 to another etc.
|
||||
// 2. Every block must eventually be fetched even if the peer sends no answer.
|
||||
// 1. If possible, blocks should be fetched in parallel.
|
||||
// height..+500 to one peer, height+500..+1000 to another etc.
|
||||
// 2. Every block must eventually be fetched even if the peer sends no answer.
|
||||
//
|
||||
// Thus, the following algorithm is used:
|
||||
// 1. Block range is divided into chunks of payload.MaxHashesCount.
|
||||
// 2. Send requests for chunk in increasing order.
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
Package rpcclient implements NEO-specific JSON-RPC 2.0 client.
|
||||
This package is currently in beta and is subject to change.
|
||||
|
||||
Client
|
||||
# Client
|
||||
|
||||
After creating a client instance with or without a ClientConfig
|
||||
you can interact with the NEO blockchain by its exposed methods.
|
||||
|
@ -12,6 +12,7 @@ return a more pretty printed response from the server instead of
|
|||
a raw hex string.
|
||||
|
||||
TODO:
|
||||
|
||||
Allow client to connect using client cert.
|
||||
More in-depth examples.
|
||||
|
||||
|
@ -75,6 +76,5 @@ Unsupported methods
|
|||
sendfrom
|
||||
sendmany
|
||||
sendtoaddress
|
||||
|
||||
*/
|
||||
package rpcclient
|
||||
|
|
|
@ -848,15 +848,16 @@ func getSigners(sender *wallet.Account, cosigners []SignerAccount) ([]transactio
|
|||
// GAS should be deposited to the Notary contract.
|
||||
// Main transaction should be constructed by the user. Several rules should be met for
|
||||
// successful main transaction acceptance:
|
||||
// 1. Native Notary contract should be a signer of the main transaction.
|
||||
// 2. Notary signer should have None scope.
|
||||
// 3. Main transaction should have dummy contract witness for Notary signer.
|
||||
// 4. Main transaction should have NotaryAssisted attribute with NKeys specified.
|
||||
// 5. NotaryAssisted attribute and dummy Notary witness (as long as the other incomplete witnesses)
|
||||
// should be paid for. Use CalculateNotaryWitness to calculate the amount of network fee to pay
|
||||
// for the attribute and Notary witness.
|
||||
// 6. Main transaction either shouldn't have all witnesses attached (in this case none of them
|
||||
// can be multisignature), or it only should have a partial multisignature.
|
||||
// 1. Native Notary contract should be a signer of the main transaction.
|
||||
// 2. Notary signer should have None scope.
|
||||
// 3. Main transaction should have dummy contract witness for Notary signer.
|
||||
// 4. Main transaction should have NotaryAssisted attribute with NKeys specified.
|
||||
// 5. NotaryAssisted attribute and dummy Notary witness (as long as the other incomplete witnesses)
|
||||
// should be paid for. Use CalculateNotaryWitness to calculate the amount of network fee to pay
|
||||
// for the attribute and Notary witness.
|
||||
// 6. Main transaction either shouldn't have all witnesses attached (in this case none of them
|
||||
// can be multisignature), or it only should have a partial multisignature.
|
||||
//
|
||||
// Note: client should be initialized before SignAndPushP2PNotaryRequest call.
|
||||
func (c *Client) SignAndPushP2PNotaryRequest(mainTx *transaction.Transaction, fallbackScript []byte, fallbackSysFee int64, fallbackNetFee int64, fallbackValidFor uint32, acc *wallet.Account) (*payload.P2PNotaryRequest, error) {
|
||||
var err error
|
||||
|
|
|
@ -141,18 +141,20 @@ func (pt *ParamType) DecodeBinary(r *io.BinReader) {
|
|||
|
||||
// ParseParamType is a user-friendly string to ParamType converter, it's
|
||||
// case-insensitive and makes the following conversions:
|
||||
// signature -> SignatureType
|
||||
// bool, boolean -> BoolType
|
||||
// int, integer -> IntegerType
|
||||
// hash160 -> Hash160Type
|
||||
// hash256 -> Hash256Type
|
||||
// bytes, bytearray, filebytes -> ByteArrayType
|
||||
// key, publickey -> PublicKeyType
|
||||
// string -> StringType
|
||||
// array, struct -> ArrayType
|
||||
// map -> MapType
|
||||
// interopinterface -> InteropInterfaceType
|
||||
// void -> VoidType
|
||||
//
|
||||
// signature -> SignatureType
|
||||
// bool, boolean -> BoolType
|
||||
// int, integer -> IntegerType
|
||||
// hash160 -> Hash160Type
|
||||
// hash256 -> Hash256Type
|
||||
// bytes, bytearray, filebytes -> ByteArrayType
|
||||
// key, publickey -> PublicKeyType
|
||||
// string -> StringType
|
||||
// array, struct -> ArrayType
|
||||
// map -> MapType
|
||||
// interopinterface -> InteropInterfaceType
|
||||
// void -> VoidType
|
||||
//
|
||||
// anything else generates an error.
|
||||
func ParseParamType(typ string) (ParamType, error) {
|
||||
switch strings.ToLower(typ) {
|
||||
|
|
|
@ -118,9 +118,10 @@ func (u Uint256) MarshalJSON() ([]byte, error) {
|
|||
}
|
||||
|
||||
// CompareTo compares two Uint256 with each other. Possible output: 1, -1, 0
|
||||
// 1 implies u > other.
|
||||
//
|
||||
// 1 implies u > other.
|
||||
// -1 implies u < other.
|
||||
// 0 implies u = other.
|
||||
// 0 implies u = other.
|
||||
func (u Uint256) CompareTo(other Uint256) int { return bytes.Compare(u[:], other[:]) }
|
||||
|
||||
// EncodeBinary implements the io.Serializable interface.
|
||||
|
|
|
@ -237,8 +237,9 @@ func (s *Stack) RemoveAt(n int) Element {
|
|||
|
||||
// Dup duplicates and returns the element at position n.
|
||||
// Dup is used for copying elements on the top of its own stack.
|
||||
// s.Push(s.Peek(0)) // will result in unexpected behavior.
|
||||
// s.Push(s.Dup(0)) // is the correct approach.
|
||||
//
|
||||
// s.Push(s.Peek(0)) // will result in unexpected behavior.
|
||||
// s.Push(s.Dup(0)) // is the correct approach.
|
||||
func (s *Stack) Dup(n int) Element {
|
||||
e := s.Peek(n)
|
||||
return Element{e.value.Dup()}
|
||||
|
@ -246,9 +247,10 @@ func (s *Stack) Dup(n int) Element {
|
|||
|
||||
// Iter iterates over all elements int the stack, starting from the top
|
||||
// of the stack.
|
||||
// s.Iter(func(elem *Element) {
|
||||
//
|
||||
// s.Iter(func(elem *Element) {
|
||||
// // do something with the element.
|
||||
// })
|
||||
// })
|
||||
func (s *Stack) Iter(f func(Element)) {
|
||||
for i := len(s.elems) - 1; i >= 0; i-- {
|
||||
f(s.elems[i])
|
||||
|
@ -257,9 +259,10 @@ func (s *Stack) Iter(f func(Element)) {
|
|||
|
||||
// IterBack iterates over all elements of the stack, starting from the bottom
|
||||
// of the stack.
|
||||
// s.IterBack(func(elem *Element) {
|
||||
//
|
||||
// s.IterBack(func(elem *Element) {
|
||||
// // do something with the element.
|
||||
// })
|
||||
// })
|
||||
func (s *Stack) IterBack(f func(Element)) {
|
||||
for i := 0; i < len(s.elems); i++ {
|
||||
f(s.elems[i])
|
||||
|
|
|
@ -36,12 +36,13 @@ var ErrTooDeep = errors.New("too deep")
|
|||
|
||||
// ToJSON encodes Item to JSON.
|
||||
// It behaves as following:
|
||||
// ByteArray -> base64 string
|
||||
// BigInteger -> number
|
||||
// Bool -> bool
|
||||
// Null -> null
|
||||
// Array, Struct -> array
|
||||
// Map -> map with keys as UTF-8 bytes
|
||||
//
|
||||
// ByteArray -> base64 string
|
||||
// BigInteger -> number
|
||||
// Bool -> bool
|
||||
// Null -> null
|
||||
// Array, Struct -> array
|
||||
// Map -> map with keys as UTF-8 bytes
|
||||
func ToJSON(item Item) ([]byte, error) {
|
||||
seen := make(map[Item]sliceNoPointer, typicalNumOfItems)
|
||||
return toJSON(nil, seen, item)
|
||||
|
@ -153,12 +154,13 @@ func itemToJSONString(it Item) ([]byte, error) {
|
|||
|
||||
// FromJSON decodes an Item from JSON.
|
||||
// It behaves as following:
|
||||
// string -> ByteArray from base64
|
||||
// number -> BigInteger
|
||||
// bool -> Bool
|
||||
// null -> Null
|
||||
// array -> Array
|
||||
// map -> Map, keys are UTF-8
|
||||
//
|
||||
// string -> ByteArray from base64
|
||||
// number -> BigInteger
|
||||
// bool -> Bool
|
||||
// null -> Null
|
||||
// array -> Array
|
||||
// map -> Map, keys are UTF-8
|
||||
func FromJSON(data []byte, maxCount int) (Item, error) {
|
||||
d := decoder{
|
||||
Decoder: *json.NewDecoder(bytes.NewReader(data)),
|
||||
|
|
Loading…
Reference in a new issue